Compare commits

..

No commits in common. "v11" and "main" have entirely different histories.
v11 ... main

5 changed files with 1 additions and 4026 deletions

3740
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
[package]
edition = "2024"
name = "web"
version = "0.1.0"
[dependencies]
fathom-function = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "main" }
pipeline-application = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "main" }
serde = { version = "1.0.219", features = ["derive"] }
serde-this-or-that = "0.5.0"
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
uom = { version = "0.36" }
uuid = { version = "1" }

View File

@ -1,88 +1,2 @@
# Add field assessment entries # 6f5428061f7340499e44e6aad76f38a7
Field inspections carried out on sections of pipelines.
Field inspections are conducted for various reasons the two most likely are for repairs and for
validation of an ILI report.
Generally for a field inspection a approximately 15 meter long pit will be dug to expose a
complete pipeline joint along with a couple of meters of the proceeding and subsequence joints.
Multiple inspections will be carried out on the exposed joint.
## Input
### Arguments
- `org_id`: as string which should be a valid `uuid` for the organization
- `project_id`: the id of the data project where the pipeline data is found
- `pipeline_id`: an `array` of `strings` which should be valid UUIDs for pipelines
- `date`: a `string` formatted as an ISO date representing the date of the field assessment
- `log_distance`: a `float` representing the log distance of the anomaly measured in meters
- `girth_weld`: a `integer` representing the girth weld number of the joint being inspected
- `anomaly_orientation_hours`: a `integer` representing the circumferential position of the
starting point of the anomaly measured in clock position the hour part
- `anomaly_orientation_minutes`: a `integer` representing the circumferential position of the
starting point of the anomaly measured in clock position the minute part
- `measured_wall_thickness`: a `float` representing the measured wall thickness from a
location not affected by corrosion (i.e the original wall thickness).
- `measured_remaining_wall_thickness`: a `float` representing the measured wall thickness from
the river bottom of the anomaly
- `surface_location`: a `string` the surface location of the anomaly being inspected possible values
- `EXT`: external
- `INT`: internal
- `MID`: midwall
- `UNK`: unknown
- `measured_length`: a `float` representing the measured length of the anomaly
- `measured_width`: a `float` representing the measured width of the anomaly
- `measured_max_depth`: a `float` representing the measured max depth of the anomaly
- `purpose_of_measurement`: a `string` the reason for the measurement (e.g. ILI verification/Repair)
- `tool_accuracy`: a `float` representing the accuracy of the measurement tool
- `pit_gauge_accuracy`: a `float` representing the accuracy of the pit gauge tool.
- `inspector`: a `string` representing the identifier of the inspector
- `remarks`: a `string` for any additional remarks about the inspection
## Creating the function on the platform
To create this function on the platform using the `cli` set up the port forwarding as shown in README.
Then run the following command to create the function.
```bash
cargo run functions create \
-f functions/field_assessment \
-d "Adds field assessment reports" \
-i org_id=string \
-i project_id=string \
-i pipeline_id=array \
-i date=string \
-i log_distance=float \
-i girth_weld=integer \
-i anomaly_orientation_hours=integer \
-i anomaly_orientation_minutes=integer \
-i measured_wall_thickness=float \
-i measured_remaining_wall_thickness=float \
-i surface_location=string \
-i measured_length=float \
-i measured_width=float \
-i measured_max_depth=float \
-i purpose_of_measurement=string \
-i tool_accuracy=float \
-i pit_gauge_accuracy=float \
-i inspector=string \
-i remarks=string
```
## Testing the function locally
You can run and test the function locally by running
```bash
cargo run
```
Then you can check it work with `curl` as follows
```bash
jq '. | tojson' functions/field_assessment/example_input.json | curl -d '@-' localhost:8080
```

View File

@ -1,23 +0,0 @@
{
"anomaly_orientation_hours": "10",
"anomaly_orientation_minutes": "26",
"date": "2018-09-15",
"girth_weld": 820,
"inspector": "jbell",
"log_distance": 1105,
"measured_length": 120,
"measured_max_depth": 1.06,
"measured_remaining_wall_thickness": null,
"measured_wall_thickness": null,
"measured_width": null,
"org_id": "2cbfe270-d195-48ad-aed1-24145924635c",
"pipeline_id": [
"01966d47-1d4c-7751-a1f1-0617caa3a00d"
],
"pit_gauge_accuracy": null,
"project_id": "680b61b0aedd6f9e639d8699",
"purpose_of_measurement": "ili_verification",
"remarks": null,
"surface_location": "EXT",
"tool_accuracy": null
}

View File

@ -1,163 +0,0 @@
use fathom_function::{chrono::NaiveDate, forms::deserialize_date, tracing};
use pipeline_application::{
application::{
Application, FieldAssessment, PurposeOfMeasurement, SurfaceLocation,
features::{FeatureIdentification, FeatureType},
orientation::Orientation,
},
serialization::{serialize_meter, serialize_millimeter, serialize_percent},
};
use serde::{Deserialize, Serialize};
use serde_this_or_that::as_opt_u64;
use uom::si::f64::{Length, Ratio};
use uuid::Uuid;
#[fathom_function::function]
async fn upload_field_assessment(input: Input) -> Result<Output, String> {
let app = Application::new_from_compile_env(input.org_id, input.project_id).unwrap();
for pipeline_id in input.pipeline_id {
app.upload_field_assessment(pipeline_id, [&input.report])
.await
.map_err(|err| {
tracing::error!(%pipeline_id, ?err, "Error uploading field assessment");
format!("{err:?}")
})?;
}
Ok(Output {
status: "Success".to_owned(),
})
}
#[derive(Debug, Serialize)]
struct Output {
status: String,
}
#[derive(Debug, Deserialize)]
struct Input {
org_id: Uuid,
project_id: String,
pipeline_id: Vec<Uuid>,
#[serde(flatten)]
report: Report,
}
#[derive(Debug, Deserialize)]
struct Report {
/// The date of this field inspection.
#[serde(deserialize_with = "deserialize_date")]
date: NaiveDate,
/// The log distance: the absolute distance measured in meters from the launcher.
#[serde(with = "serialize_meter")]
log_distance: Length,
/// The Girthweld number. These follow a sequential order of 10 (e.g., 10, 20, 30, ...) to
/// enumerate each joint from the initial to the final one. This ordering system facilitates
/// future repairs using the "Pipeline Sectional Replacement" method.
#[serde(deserialize_with = "as_opt_u64")]
girth_weld: Option<u64>,
/// The circumferential position of the starting point of an anomaly, specifically the top-left
/// position on the pipe.
///
/// This orientation is measured in O'clock notation, ranging from 00:00 to 12:00, indicating
/// the position around the circumference of the pipe. This is the number of hours
#[serde(deserialize_with = "as_opt_u64")]
anomaly_orientation_hours: Option<u64>,
/// The circumferential position of the starting point of an anomaly, specifically the top-left
/// position on the pipe.
///
/// This orientation is measured in O'clock notation, ranging from 00:00 to 12:00, indicating
/// the position around the circumference of the pipe. This is the number of minutes
#[serde(deserialize_with = "as_opt_u64")]
anomaly_orientation_minutes: Option<u64>,
/// The measured wall thickness of the pipeline taken from an un-corroded location. Corresponds
/// to the un-corroded wall thickness.
#[serde(with = "serialize_millimeter::opt")]
measured_wall_thickness: Option<Length>,
/// The measured wall thickness of the pipeline taken from the river bottom of the corrosion.
#[serde(with = "serialize_millimeter::opt")]
measured_remaining_wall_thickness: Option<Length>,
/// The surface location of the anomaly.
///
/// Each identified anomaly, denoted as ANOM, falls into one of four categories: Internal
/// (INT), External (EXT), Midwall (MID), or Unknown (UNK) for any reason. These
/// classifications are assigned based on the specific characteristics and location of the
/// anomaly on the pipeline. The categorization helps provide a comprehensive understanding of
/// the nature of the anomalies present.
surface_location: Option<SurfaceLocation>,
/// The measured length (in mm) of an anomaly, (the length of the corrosion box) in relation to
/// the reporting threshold.
#[serde(with = "serialize_millimeter")]
measured_length: Length,
/// The circumferential width of an anomaly, this denotes the measured measurement of the
/// anomaly's width in circumferential direction, comparable to the width of the corrosion box,
/// concerning the reporting threshold and the unit is mm.
#[serde(with = "serialize_millimeter::opt")]
measured_width: Option<Length>,
/// The measured depth of the anomaly.
///
/// This measurement is essential for evaluating the structural integrity of the pipeline. A
/// higher percentage of metal loss indicates a more significant impact on the pipeline's
/// strength and durability.
#[serde(with = "serialize_percent")]
measured_max_depth: Ratio,
/// The reason for this field assessment
purpose_of_measurement: PurposeOfMeasurement,
/// The accuracy of the tool used
#[serde(with = "serialize_millimeter::opt")]
tool_accuracy: Option<Length>,
/// The accuracy of the pit gauge used
#[serde(with = "serialize_millimeter::opt")]
pit_gauge_accuracy: Option<Length>,
/// The inspector name or identifier
inspector: String,
/// And additional remarks about the inspection
remarks: Option<String>,
}
impl Report {
fn orientation(&self) -> Option<Orientation> {
Some(Orientation::new(
self.anomaly_orientation_hours? as _,
self.anomaly_orientation_minutes? as _,
))
}
}
impl From<&Report> for FieldAssessment {
fn from(value: &Report) -> Self {
Self {
date: value.date.and_time(Default::default()).and_utc(),
log_distance: value.log_distance,
feature_type: Some(FeatureType::ANOM),
feature_identification: Some(FeatureIdentification::CORR),
girth_weld: value.girth_weld.map(|v| v as _),
anomaly_orientation: value.orientation(),
measured_wall_thickness: value.measured_wall_thickness,
measured_remaining_wall_thickness: value.measured_remaining_wall_thickness,
surface_location: value.surface_location,
measured_length: value.measured_length,
measured_width: value.measured_width,
measured_max_depth: value.measured_max_depth,
purpose_of_measurement: value.purpose_of_measurement.to_owned(),
tool_accuracy: value.tool_accuracy,
pit_gauge_accuracy: value.pit_gauge_accuracy,
inspector: value.inspector.to_owned(),
remarks: value.remarks.to_owned(),
}
}
}