Compare commits
No commits in common. "v12" and "main" have entirely different histories.
3740
Cargo.lock
generated
3740
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
13
Cargo.toml
@ -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" }
|
||||
88
README.md
88
README.md
@ -1,88 +1,2 @@
|
||||
# Add field assessment entries
|
||||
# 3d848d0d4e654816b99054ab0b815367
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
@ -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
|
||||
}
|
||||
163
src/main.rs
163
src/main.rs
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user