// Take an array of prospective trees where each tree contains // an array of diamaters, one for each year the tree is alive, // and return an array of eco calulations, one for each year // // Trees will die of as part of the scenario, so the // `diameters` arrays for the trees may have different // lengths. Trees that die may be replaced with other trees, // so there will be trees that appear in the scenario at t > // 0, so the `diameters` array may have initial elements set // to 0. // // Specifying a "region" for an individual tree will override the // scenario-level "region" value. // // The "years" parameter must be >= the length of the longest // "diameters" array under "scenario_trees". // // Request (with bogus example parameters): // // POST /eco_scenario.json // // { // "region": "NoEastXXX", // "instance_id": 1, // "years": 3 // "scenario_trees": [ // { // "otmcode": "CACO", // "species_id": 1, // "region": "NoEastXXX", // "diameters": [1, 1.3, 1.7] // } // ] // } // // Response (with bogus example values): // // { // "Years": [ // { // "aq_nox_avoided": 0.01548490, // "aq_nox_dep": 0.00771784, // "aq_pm10_avoided": 0.00546863 // }, // { // "aq_nox_avoided": 0.02548420, // "aq_nox_dep": 0.01973722, // "aq_pm10_avoided": 0.00676823 // }, // { // "aq_nox_avoided": 0.05484902, // "aq_nox_dep": 0.04774471, // "aq_pm10_avoided": 0.00946822 // } // ], // "Total": { // "aq_nox_avoided": ... , // "aq_nox_dep": ... , // "aq_pm10_avoided": ... // } // } func EcoScenarioPOST(cache *cache.Cache) func(*ScenarioPostData) (*Scenario, error) { return func(data *ScenarioPostData) (*Scenario, error) { t := time.Now() scenarioTrees := data.Scenario_trees scenarioRegion := data.Region instanceId, err := strconv.Atoi(data.Instance_id) if err != nil { return nil, err } if len(scenarioRegion) == 0 { var regions []eco.Region regions, err = cache.Db.GetRegionsForInstance( cache.RegionGeometry, instanceId) if err != nil { return nil, err } if len(regions) == 1 { scenarioRegion = regions[0].Code } } yearTotals := make([][]float64, data.Years) grandTotals := make([]float64, len(eco.Factors)) for i := range yearTotals { yearTotals[i] = make([]float64, len(eco.Factors)) } for _, tree := range scenarioTrees { effectiveRegion := scenarioRegion if len(tree.Region) != 0 { effectiveRegion = tree.Region } factorDataForRegion, found := cache.RegionData[effectiveRegion] if !found { return nil, errors.New("No data is available for the iTree region with code " + effectiveRegion) } itreecode, err := cache.GetITreeCode(tree.Otmcode, tree.Species_id, effectiveRegion, instanceId) if err != nil { return nil, err } for i, diameter := range tree.Diameters { factorSum := make([]float64, len(eco.Factors)) eco.CalcOneTree( factorDataForRegion, itreecode, diameter, factorSum) for j, value := range factorSum { yearTotals[i][j] = value grandTotals[j] += value } } } // The requests are written to stdout like this: // 2014/07/15 14:06:10 POST /eco_scenario.json // Indenting the timing report aligns it with the http // verb on the previous line. fmt.Println(" ", int64(time.Since(t)/time.Millisecond), "ms (total)") years := make([]map[string]float64, data.Years) for i, a := range yearTotals { years[i] = eco.FactorArrayToMap(a) } return &Scenario{ Total: eco.FactorArrayToMap(grandTotals), Years: years}, nil } }
func EcoGET(cache *cache.Cache) func(url.Values) (*BenefitsWrapper, error) { return func(in url.Values) (*BenefitsWrapper, error) { instanceid, err := getSingleIntValue(in, "instanceid") if err != nil { return nil, err } speciesid, err := getSingleIntValue(in, "speciesid") if err != nil { return nil, err } otmcode, err := getSingleValue(in, "otmcode") if err != nil { return nil, err } diameterstr, err := getSingleValue(in, "diameter") if err != nil { return nil, err } diameter, err := strconv.ParseFloat(diameterstr, 64) if err != nil { return nil, err } diameter = diameter * eco.CentimetersPerInch region, err := getSingleValue(in, "region") if err != nil { return nil, err } factorDataForRegion, found := cache.RegionData[region] if !found { return nil, errors.New("invalid region") } itreecode, err := cache.GetITreeCode(otmcode, speciesid, region, instanceid) if err != nil { return nil, err } factorsum := make([]float64, len(eco.Factors)) eco.CalcOneTree( factorDataForRegion, itreecode, diameter, factorsum) return &BenefitsWrapper{Benefits: eco.FactorArrayToMap(factorsum)}, nil } }