changeset 5197:c352dbbf2778 new-fwa

Started with loading limiting factors and validities.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 07 May 2020 17:50:29 +0200
parents 5bc8daa986d9
children 0e91d200299d
files pkg/controllers/fwa.go
diffstat 1 files changed, 103 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/fwa.go	Thu May 07 16:25:58 2020 +0200
+++ b/pkg/controllers/fwa.go	Thu May 07 17:50:29 2020 +0200
@@ -14,14 +14,99 @@
 package controllers
 
 import (
+	"context"
+	"database/sql"
 	"log"
 	"net/http"
 	"time"
 
+	"github.com/gorilla/mux"
+
 	"gemma.intevation.de/gemma/pkg/common"
-	"github.com/gorilla/mux"
+	"gemma.intevation.de/gemma/pkg/middleware"
+)
+
+const (
+	selectBottlenecksLimitingSQL = `
+SELECT
+  lower(validity),
+  upper(validity),
+  limiting
+FROM
+  waterway.bottlenecks
+WHERE
+  bottleneck_id = $1 AND
+  validity && tstzrange($2, $3)`
+)
+
+type (
+	limitingValidity struct {
+		limiting string
+		lower    time.Time
+		upper    time.Time
+	}
+
+	limitingValidities []limitingValidity
 )
 
+func (lv *limitingValidity) intersects(from, to time.Time) bool {
+	return !(to.Before(lv.lower) || from.After(lv.upper))
+}
+
+func (lvs limitingValidities) find() func(from, to time.Time) *limitingValidity {
+
+	var last *limitingValidity
+
+	return func(from, to time.Time) *limitingValidity {
+		if last != nil && last.intersects(from, to) {
+			return last
+		}
+		for i := range lvs {
+			if lv := &lvs[i]; lv.intersects(from, to) {
+				last = lv
+				return lv
+			}
+		}
+		return nil
+	}
+}
+
+func loadLimitingValidities(
+	ctx context.Context,
+	conn *sql.Conn,
+	bottleneckID string,
+	from, to time.Time,
+) (limitingValidities, error) {
+
+	var lvs limitingValidities
+
+	rows, err := conn.QueryContext(
+		ctx,
+		selectLimitingSQL,
+		from, to)
+
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+
+	for rows.Next() {
+		var lv limitingValidity
+		if err := rows.Scan(
+			&lv.limiting,
+			&lv.lower,
+			&lv.upper,
+		); err != nil {
+			return nil, err
+		}
+		lv.lower = lv.lower.UTC()
+		lv.upper = lv.upper.UTC()
+		lvs = append(lvs, lv)
+	}
+
+	return lvs, rows.Err()
+}
+
 func fairwayAvailability(rw http.ResponseWriter, req *http.Request) {
 
 	vars := mux.Vars(req)
@@ -29,14 +114,12 @@
 	switch vars["kind"] {
 	case "bottleneck":
 		fairwayAvailabilityBottleneck(rw, req)
-	case "stretch":
-	case "section":
+	case "stretch": // TODO: Implement me!
+	case "section": // TODO: Implement me!
 	default:
 		http.Error(rw, "Invalid kind type.", http.StatusBadRequest)
 		return
 	}
-
-	// TODO: Implement me!
 }
 
 func parseFromTo(
@@ -77,8 +160,21 @@
 		return
 	}
 
+	ctx := req.Context()
+	conn := middleware.GetDBConn(req)
+
+	lvs, err := loadLimitingValidities(
+		ctx,
+		conn,
+		bottleneckID,
+		from, to)
+	if err != nil {
+		log.Printf("error: %v\n", err)
+		http.Error(rw, "Loading validities failed", http.StatusInternalServerError)
+		return
+	}
+
 	// TODO: Implement me!
-	_ = from
-	_ = to
 	_ = los
+	_ = lvs
 }