changeset 3392:96d3af15fc28

available fairway depth: Decide if width or depth is critial by looking at the bottleneck limiting factor.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 22 May 2019 18:00:53 +0200
parents 11379474a1b1
children cf0b5274698a
files pkg/controllers/bottlenecks.go
diffstat 1 files changed, 50 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/bottlenecks.go	Wed May 22 17:00:02 2019 +0200
+++ b/pkg/controllers/bottlenecks.go	Wed May 22 18:00:53 2019 +0200
@@ -32,11 +32,15 @@
 )
 
 const (
+	selectLimitingSQL = `
+SELECT limiting from waterway.bottlenecks WHERE objnam = $1`
+
 	selectAvailableDepthSQL = `
 WITH data AS (
   SELECT
     efa.measure_date,
     efa.available_depth_value,
+    efa.available_width_value,
     efa.water_level_value
   FROM waterway.effective_fairway_availability efa
   JOIN waterway.fairway_availability fa
@@ -47,7 +51,8 @@
     bn.objnam = $1 AND
     efa.level_of_service = $2 AND
     efa.measure_type = 'Measured' AND
-    efa.available_depth_value IS NOT NULL AND
+    (efa.available_depth_value IS NOT NULL OR
+     efa.available_width_value IS NOT NULL) AND
     efa.water_level_value IS NOT NULL
 ),
 before AS (
@@ -102,8 +107,9 @@
 
 	availMeasurement struct {
 		when  time.Time
-		depth int
-		value int
+		depth int16
+		width int16
+		value int16
 	}
 
 	availMeasurements []availMeasurement
@@ -124,6 +130,22 @@
 	return float64(measurement.value)
 }
 
+func (measurement *availMeasurement) getWidth() float64 {
+	return float64(measurement.width)
+}
+
+func limitingFactor(limiting string) func(*availMeasurement) float64 {
+	switch limiting {
+	case "depth":
+		return (*availMeasurement).getDepth
+	case "width":
+		return (*availMeasurement).getWidth
+	default:
+		log.Printf("warn: unknown limitation '%s'. default to 'depth'", limiting)
+		return (*availMeasurement).getDepth
+	}
+}
+
 func (measurements availMeasurements) classify(
 	from, to time.Time,
 	breaks []referenceValue,
@@ -284,7 +306,12 @@
 
 	for rows.Next() {
 		var m availMeasurement
-		if err := rows.Scan(&m.when, &m.depth, &m.value); err != nil {
+		if err := rows.Scan(
+			&m.when,
+			&m.depth,
+			&m.width,
+			&m.value,
+		); err != nil {
 			return nil, err
 		}
 		m.when = m.when.UTC()
@@ -616,6 +643,23 @@
 	conn := middleware.GetDBConn(req)
 	ctx := req.Context()
 
+	var limiting string
+	err := conn.QueryRowContext(ctx, selectLimitingSQL, bn).Scan(&limiting)
+	switch {
+	case err == sql.ErrNoRows:
+		http.Error(
+			rw, fmt.Sprintf("Unknown limitation for %s.", bn),
+			http.StatusNotFound)
+		return
+	case err != nil:
+		http.Error(
+			rw, fmt.Sprintf("DB error: %v.", err),
+			http.StatusInternalServerError)
+		return
+	}
+
+	access := limitingFactor(limiting)
+
 	// load the measurements
 	ms, err := loadDepthValues(ctx, conn, bn, los, from, to)
 	if err != nil {
@@ -684,13 +728,13 @@
 		ranges := ms.classify(
 			pfrom, pto,
 			breaks,
-			(*availMeasurement).getDepth,
+			access,
 		)
 
 		ldc := ms.classify(
 			pfrom, pto,
 			ldcRefs,
-			(*availMeasurement).getDepth,
+			access,
 		)
 
 		record[0] = label