Pārlūkot izejas kodu

Merge branch 'general-table' into develop

wilitp 4 gadi atpakaļ
vecāks
revīzija
8908664fc6

+ 172 - 0
app/src/api/mocks.ts

@@ -0,0 +1,172 @@
+// Utilidad para simular requests durante desarrollo
+export const mockRequest = (
+  success: Boolean,
+  payload: string,
+  timeout: number | null
+): Promise<string> => {
+  return new Promise((resolve, reject) => {
+    setTimeout(() => {
+      if (success) {
+        resolve(payload);
+      } else {
+        reject(payload);
+      }
+    }, timeout || 1000);
+  });
+};
+
+export const mockPayloads = {
+  seasonsSummariesTable: `
+    [
+      {
+        "station": {
+          "name": "excepteur",
+          "code": "6dd49d1c-68ee-4e68-b993-0ca6489c478c"
+        },
+        "from": "2016-12-22T02:14:38 +03:00",
+        "to": "2015-12-02T10:22:04 +03:00",
+        "lt10": 30.48,
+        "gt30": 13.65,
+        "gt33": 21.98,
+        "grados_acumulados": 18.67,
+        "amplitud_termica": 19.95,
+        "precip_acumulada": 11.53,
+        "dias_para_igualar_temporada": -8
+      },
+      {
+        "station": {
+          "name": "excepteur",
+          "code": "6dd49d1c-68ee-4e68-b993-0ca6489c478c"
+        },
+        "from": "2014-08-02T04:29:26 +03:00",
+        "to": "2014-06-18T08:59:25 +03:00",
+        "lt10": 30.8,
+        "gt30": 15.51,
+        "gt33": 27.18,
+        "grados_acumulados": 15.31,
+        "amplitud_termica": 13.78,
+        "precip_acumulada": 15.58,
+        "dias_para_igualar_temporada": -2
+      },
+      {
+        "station": {
+          "name": "excepteur",
+          "code": "6dd49d1c-68ee-4e68-b993-0ca6489c478c"
+        },
+        "from": "2017-04-30T08:01:55 +03:00",
+        "to": "2021-05-03T05:35:16 +03:00",
+        "lt10": 19.58,
+        "gt30": 29.96,
+        "gt33": 17.12,
+        "grados_acumulados": 13.11,
+        "amplitud_termica": 31.6,
+        "precip_acumulada": 23.31,
+        "dias_para_igualar_temporada": -10
+      },
+      {
+        "station": {
+          "name": "excepteur",
+          "code": "6dd49d1c-68ee-4e68-b993-0ca6489c478c"
+        },
+        "from": "2016-07-28T06:30:57 +03:00",
+        "to": "2015-04-29T02:19:31 +03:00",
+        "lt10": 34.5,
+        "gt30": 24.31,
+        "gt33": 38.21,
+        "grados_acumulados": 18.47,
+        "amplitud_termica": 10.49,
+        "precip_acumulada": 24.36,
+        "dias_para_igualar_temporada": 7
+      },
+      {
+        "station": {
+          "name": "excepteur",
+          "code": "6dd49d1c-68ee-4e68-b993-0ca6489c478c"
+        },
+        "from": "2019-08-21T08:41:01 +03:00",
+        "to": "2014-07-05T03:50:04 +03:00",
+        "lt10": 12.94,
+        "gt30": 16.74,
+        "gt33": 21.02,
+        "grados_acumulados": 37.22,
+        "amplitud_termica": 31.71,
+        "precip_acumulada": 10.77,
+        "dias_para_igualar_temporada": -4
+      }
+    ]
+  `,
+  general: `
+    [
+      {
+        "station": {
+          "name": "consequat",
+          "code": "b7d147cb-a5f0-4a55-b6d9-8934b7085f13"
+        },
+        "from": "2015-02-15T02:03:07 +03:00",
+        "to": "2018-05-19T10:42:45 +03:00",
+        "lt10": 23.81,
+        "gt30": 30.49,
+        "gt33": 25.3,
+        "grados_acumulados": 20.88,
+        "amplitud_termica": 36,
+        "precip_acumulada": 21.64
+      },
+      {
+        "station": {
+          "name": "dolor",
+          "code": "b3414719-92ad-4977-985b-e9e6f5d09312"
+        },
+        "from": "2014-03-22T06:51:34 +03:00",
+        "to": "2018-01-27T07:58:57 +03:00",
+        "lt10": 37.58,
+        "gt30": 12.2,
+        "gt33": 32.12,
+        "grados_acumulados": 31.02,
+        "amplitud_termica": 39.29,
+        "precip_acumulada": 12.01
+      },
+      {
+        "station": {
+          "name": "dolore",
+          "code": "889d2e8b-45fd-4342-88ae-1de44b58409c"
+        },
+        "from": "2020-09-27T02:05:22 +03:00",
+        "to": "2021-09-16T10:24:50 +03:00",
+        "lt10": 32.2,
+        "gt30": 30.93,
+        "gt33": 32.54,
+        "grados_acumulados": 26.78,
+        "amplitud_termica": 24.5,
+        "precip_acumulada": 21.59
+      },
+      {
+        "station": {
+          "name": "eu",
+          "code": "62fada45-6f04-40b4-95a1-99959b82145c"
+        },
+        "from": "2019-02-08T12:46:41 +03:00",
+        "to": "2021-06-01T07:29:53 +03:00",
+        "lt10": 14.25,
+        "gt30": 10.34,
+        "gt33": 30.31,
+        "grados_acumulados": 29,
+        "amplitud_termica": 25.09,
+        "precip_acumulada": 33.63
+      },
+      {
+        "station": {
+          "name": "officia",
+          "code": "6cca9007-ea5b-496b-9e7b-a520416a6564"
+        },
+        "from": "2018-06-26T08:18:13 +03:00",
+        "to": "2020-03-27T09:04:18 +03:00",
+        "lt10": 38.79,
+        "gt30": 34.99,
+        "gt33": 36.03,
+        "grados_acumulados": 18.87,
+        "amplitud_termica": 26.55,
+        "precip_acumulada": 30.38
+      }
+    ]
+  `,
+};

+ 15 - 0
app/src/api/tables.ts

@@ -0,0 +1,15 @@
+import { mockPayloads, mockRequest } from "./mocks";
+// Quizas llamarlos table no hacia falta,
+// pero es preferible antes de que a alguien se le olvide usar un alias cuando importe estas funciones.
+
+export const generalTable = (from: string, to: string, year: string) => {
+  return mockRequest(true, mockPayloads.general, null);
+};
+
+export const seasonsSummariesTable = (
+  from: string,
+  to: string,
+  year: string
+) => {
+  return mockRequest(true, mockPayloads.seasonsSummariesTable, null);
+};

+ 67 - 0
app/src/components/UI/dashboard/cockpit/index.tsx

@@ -0,0 +1,67 @@
+import React, { useContext, ChangeEvent, FC } from "react";
+import Select from "../../forms/select";
+import CalendarInput from "../../forms/calendarInput";
+import {
+  DispatchContext,
+  StateContext,
+} from "../../../../context/dashboard/Provider";
+import * as actions from "../../../../context/dashboard/actions";
+
+const fincaList: string[] | number[] = ["a", "b", "c", "d"];
+const campaignList: string[] | number[] = ["2018", "2019", "2020", "2021"];
+
+const Cockpit: FC = () => {
+  const dashboardState = useContext(StateContext);
+  const dashboardDispatch = useContext(DispatchContext);
+
+  return (
+    <section className="row p-lg-4 p-md-3 p-2">
+      <div className="col-12 col-lg-4 mb-2 col-xl-3 mb-xl-0">
+        <Select
+          list={fincaList}
+          onChange={(e: ChangeEvent<HTMLInputElement>) =>
+            console.log(e.target.value)
+          }
+          name="Comparación"
+          placeholder="Fincas"
+        />
+      </div>
+      <div className="col-6 col-lg-4 mb-2 col-xl-auto mb-xl-0">
+        <CalendarInput
+          onChange={(e: ChangeEvent<HTMLInputElement>) =>
+            dashboardDispatch(actions.setFromControl(e.target.value))
+          }
+          value={dashboardState.from}
+          name="Comparación"
+        />
+      </div>
+      <div className="col-6 col-lg-4 mb-2 col-xl-auto mb-xl-0">
+        <CalendarInput
+          onChange={(e: ChangeEvent<HTMLInputElement>) =>
+            dashboardDispatch(actions.setToControl(e.target.value))
+          }
+          value={dashboardState.to}
+          name="Comparación"
+        />
+      </div>
+      <div className="col-6 col-lg-4 mb-2 col-xl-auto mb-xl-0">
+        <Select
+          list={campaignList}
+          onChange={(e: ChangeEvent<HTMLInputElement>) =>
+            dashboardDispatch(actions.setYearControl(e.target.value))
+          }
+          value={dashboardState.year}
+          name="Comparación"
+          placeholder="Año historicos"
+        />
+      </div>
+
+      <div className="col-auto">
+        <button type="button" className="btn btn-primary">
+          Aplicar
+        </button>
+      </div>
+    </section>
+  );
+};
+export default Cockpit;

+ 16 - 14
app/src/components/UI/forms/calendarInput.tsx

@@ -1,24 +1,26 @@
 import React, { FC, useState } from "react";
 
 interface calendarInputProps {
-    onChange: Function;
-    name: string;
-    value?: string;
-    min?: string;
-    max?: string;
-    [index: string]: any;
+  onChange: Function;
+  name: string;
+  value?: string | null;
+  min?: string;
+  max?: string;
+  [index: string]: any;
 }
 
 const CalendarInput: FC<calendarInputProps> = ({ className, ...props }) => {
+  const defaultValue = new Date().toISOString().substr(0, 10);
 
-    const [startDate, setStartDate] = useState(new Date());
-
-    return (
-        <input {...(props as any)}
-            defaultValue={startDate.toISOString().substr(0, 10)}
-            className={`form-control ${className}`}
-            type="date" id="start" />
-    );
+  return (
+    <input
+      {...(props as any)}
+      defaultValue={defaultValue}
+      className={`form-control ${className}`}
+      type="date"
+      id="start"
+    />
+  );
 };
 
 export default CalendarInput;

+ 39 - 42
app/src/components/data/TemperaturePerSeason/index.tsx

@@ -1,50 +1,47 @@
-import React, { FC } from "react";
+import React, { FC, useEffect, useState } from "react";
+import { seasonsSummariesTable } from "../../../api/tables";
+import { Summary } from "../../../types/summary";
 import { TableHeader as Header, TdGroup } from "../shared";
 import * as classes from "../tables.module.css";
 
 const TemperaturePerSeason: FC = () => {
+  const [data, setData] = useState<Summary[] | null>(null);
+
+  useEffect(() => {
+    seasonsSummariesTable("", "", "").then((res) => {
+      setData(JSON.parse(res));
+    });
+  }, []);
+
+  const rows = data?.map((x) => (
+    <tr>
+      <th className={classes.cell}>Temporada 2015-2016 - Vendimia 2016</th>
+      <TdGroup>
+        <td>4,51%</td>
+        <td>17,86%</td>
+        <td>8,84%</td>
+      </TdGroup>
+      <td className={classes.cell}>{x.grados_acumulados}</td>
+      <td className={classes.cell}>{x.amplitud_termica}</td>
+      <td className={classes.cell}>{x.precip_acumulada}</td>
+      <td className={classes.cell}>{x.dias_para_igualar_temporada}</td>
+    </tr>
+  ));
+
   return (
-    <table className={classes.table}>
-      <Header daysToMatchCurrentTemperature={true} />
-      <tbody>
-        <tr>
-          <th className={classes.cell}>Temporada 2015-2016 - Vendimia 2016</th>
-          <TdGroup>
-            <td>4,51%</td>
-            <td>17,86%</td>
-            <td>8,84%</td>
-          </TdGroup>
-          <td className={classes.cell}>2215</td>
-          <td className={classes.cell}>(+)10 días</td>
-          <td className={classes.cell}>15,1</td>
-          <td className={classes.cell}>357</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>Temporada 2016-2017 - Vendimia 2017</th>
-          <TdGroup>
-            <td>4,51%</td>
-            <td>17,86%</td>
-            <td>8,84%</td>
-          </TdGroup>
-          <td className={classes.cell}>2215</td>
-          <td className={classes.cell}>(+)10 días</td>
-          <td className={classes.cell}>15,1</td>
-          <td className={classes.cell}>357</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>Temporada 2016-2017 - Vendimia 2017</th>
-          <TdGroup>
-            <td>4,51%</td>
-            <td>17,86%</td>
-            <td>8,84%</td>
-          </TdGroup>
-          <td className={classes.cell}>2215</td>
-          <td className={classes.cell}>(+)10 días</td>
-          <td className={classes.cell}>15,1</td>
-          <td className={classes.cell}>357</td>
-        </tr>
-      </tbody>
-    </table>
+    <>
+      <table className={classes.table}>
+        <Header daysToMatchCurrentTemperature={true} />
+        <tbody>{data && rows}</tbody>
+      </table>
+      {!data && (
+        <div className="d-flex py-3 justify-content-center">
+          <div className="spinner-border" role="status">
+            <span className="visually-hidden">Loading...</span>
+          </div>
+        </div>
+      )}
+    </>
   );
 };
 export default TemperaturePerSeason;

+ 42 - 84
app/src/components/data/TemperaturePerSector/index.tsx

@@ -1,92 +1,50 @@
-import React, { FC } from "react";
+import React, { useState, useEffect, FC } from "react";
+import { generalTable } from "../../../api/tables";
+import { Summary } from "../../../types/summary";
 import { TableHeader as Header, TdGroup } from "../shared";
 import * as classes from "../tables.module.css";
 
 const TemperaturePerSector: FC = () => {
+  const [data, setData] = useState<Summary[] | null>(null);
+
+  useEffect(() => {
+    generalTable("", "", "").then((res) => {
+      setData(JSON.parse(res));
+    });
+  }, []);
+
+  // Formato de los summaries(filas)
+  const rows = data?.map((x) => (
+    <tr key={x.station.code}>
+      <th className={classes.cell}>{x.station.name}</th>
+      <TdGroup>
+        <td>{x.lt10}%</td>
+        <td>{x.gt30}%</td>
+        <td>{x.gt33}%</td>
+      </TdGroup>
+      <td className={classes.cell}>{x.grados_acumulados}</td>
+      <td className={classes.cell}>{x.amplitud_termica}</td>
+      <td className={classes.cell}>{x.precip_acumulada}</td>
+    </tr>
+  ));
+
+  // Tabla
   return (
-    <table className={classes.table}>
-      <Header daysToMatchCurrentTemperature={false}/>
-      <tbody>
-        {/* Esto va a ser dinamico */}
-        <tr>
-          <th className={classes.cell}>Paraje Altamira</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>San Pablo</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>Gualtallary</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>Vista Flores</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>La Ribera</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>Maipú</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-        <tr>
-          <th className={classes.cell}>Santa Rosa</th>
-          <TdGroup>
-            <td>8,58%</td>
-            <td>7,28%</td>
-            <td>1,72%</td>
-          </TdGroup>
-          <td className={classes.cell}>16%</td>
-          <td className={classes.cell}>16.0</td>
-          <td className={classes.cell}>523</td>
-        </tr>
-      </tbody>
-    </table>
+    <>
+      <table className={classes.table}>
+        <Header daysToMatchCurrentTemperature={false} />
+        {/* Mostrar las filas si hay data */}
+        <tbody>{data && rows}</tbody>
+      </table>
+      {/* Si no hay data, mostrar una spinner abajo de la tabla */}
+      {!data && (
+        <div className="d-flex py-3 justify-content-center">
+          <div className="spinner-border" role="status">
+            <span className="visually-hidden">Loading...</span>
+          </div>
+        </div>
+      )}
+    </>
   );
 };
 export default TemperaturePerSector;

+ 14 - 69
app/src/components/pages/Home.tsx

@@ -1,18 +1,15 @@
-import React, { useContext, ChangeEvent, FC } from "react";
-import Select from "../UI/forms/select";
-import DegreeDay from "../data/DegreeDay";
-import TemperaturePerSeason from "../data/TemperaturePerSeason";
+import React, { useContext, FC } from "react";
+// import DegreeDay from "../data/DegreeDay";
+// import TemperaturePerSeason from "../data/TemperaturePerSeason";
 import TemperaturePerSector from "../data/TemperaturePerSector";
-import Precipitation from "../data/Precipitation";
-import CalendarInput from "../UI/forms/calendarInput";
+// import Precipitation from "../data/Precipitation";
 import { UserStateContext } from "../../context/auth/AuthProvider";
+import DashboardProvider from "../../context/dashboard/Provider";
 import { Redirect } from "react-router-dom";
 import Layout from "../layout";
+import Cockpit from "../UI/dashboard/cockpit";
 
 const Home: FC = () => {
-  let fincaList: string[] | number[] = ["a", "b", "c", "d"];
-  let campaignList: string[] | number[] = ["2018", "2019", "2020", "2021"];
-
   const userState = useContext(UserStateContext);
 
   if (!userState.loggedIn) {
@@ -22,67 +19,15 @@ const Home: FC = () => {
   return (
     <>
       <Layout>
-        <section className="row p-lg-4 p-md-3 p-2">
-          <div className="col-12 col-lg-4 mb-2 col-xl-3 mb-xl-0">
-            <Select
-              list={fincaList}
-              onChange={(e: ChangeEvent<HTMLInputElement>) =>
-                console.log(e.target.value)
-              }
-              name="Comparación"
-              placeholder="Fincas"
-            />
-          </div>
-          <div className="col-6 col-lg-4 mb-2 col-xl-auto mb-xl-0">
-            <CalendarInput
-              onChange={(e: ChangeEvent<HTMLInputElement>) =>
-                console.log(e.target.value)
-              }
-              name="Comparación"
-            />
-          </div>
-          <div className="col-6 col-lg-4 mb-2 col-xl-auto mb-xl-0">
-            <CalendarInput
-              onChange={(e: ChangeEvent<HTMLInputElement>) =>
-                console.log(e.target.value)
-              }
-              name="Comparación"
-            />
-          </div>
-          <div className="col-6 col-lg-4 mb-2 col-xl-auto mb-xl-0">
-            <Select
-              list={campaignList}
-              onChange={(e: ChangeEvent<HTMLInputElement>) =>
-                console.log(e.target.value)
-              }
-              name="Comparación"
-              placeholder="Año historicos"
-            />
-          </div>
-
-          <div className="col-auto">
-            <button type="button" className="btn btn-primary">
-              Aplicar
-            </button>
-          </div>
-        </section>
+        <DashboardProvider>
+          <Cockpit />
 
-        {/* <section className="row"> */}
-        {/*   <div className="col-xl-6"> */}
-        {/*     <TemperaturePerSeason /> */}
-        {/*     <DegreeDay */}
-        {/*       title={"Vista flores"} */}
-        {/*       periodString={"1ro Octubre - 31 Marzo"} */}
-        {/*     /> */}
-        {/*     <Precipitation */}
-        {/*       title={"Maipú"} */}
-        {/*       periodString={"1ro Octubre - 31 Marzo"} */}
-        {/*     /> */}
-        {/*   </div> */}
-        {/*   <div className="col-xl-6"> */}
-        {/*     <TemperaturePerSector /> */}
-        {/*   </div> */}
-        {/* </section> */}
+          <section className="row">
+            <div className="col-xl-8">
+              <TemperaturePerSector />
+            </div>
+          </section>
+        </DashboardProvider>
       </Layout>
     </>
   );

+ 38 - 0
app/src/context/dashboard/Provider.tsx

@@ -0,0 +1,38 @@
+import React, { createContext, useReducer, Dispatch, FC } from "react";
+import reducer, { State, defaultState } from "./reducer";
+import { Action } from "./actionTypes";
+
+const Provider: FC = ({ children }) => {
+  const [state, dispatch] = useReducer(reducer, defaultState);
+
+  return (
+    <StateContext.Provider value={state}>
+      <DispatchContext.Provider value={asyncDispatchWrap(dispatch)}>
+        {children}
+      </DispatchContext.Provider>
+    </StateContext.Provider>
+  );
+};
+
+type AsyncDispatch = (
+  action: Action | ((...args: any) => Promise<any>)
+) => void;
+
+function asyncDispatchWrap(dispatch: Dispatch<Action>) {
+  const asyncDispatch: AsyncDispatch = (action) => {
+    if (action instanceof Function) {
+      action(dispatch);
+      return;
+    }
+    dispatch(action);
+  };
+
+  return asyncDispatch;
+}
+
+export const StateContext = createContext<State>({});
+export const DispatchContext = createContext<
+  (action: Action | ((...args: any) => Promise<any>)) => void
+>(asyncDispatchWrap((dispatch) => {}));
+
+export default Provider;

+ 11 - 0
app/src/context/dashboard/actionTypes.ts

@@ -0,0 +1,11 @@
+export type ActionType =
+  | "SET_FROM_CONTROL"
+  | "SET_TO_CONTROL"
+  | "SET_YEAR_CONTROL";
+
+export type Action = {
+  type: ActionType;
+  to?: string | null;
+  from?: string | null;
+  year?: string | null;
+};

+ 18 - 0
app/src/context/dashboard/actions.ts

@@ -0,0 +1,18 @@
+import { Action } from "./actionTypes";
+
+export const setYearControl = (year: string): Action => ({
+  type: "SET_YEAR_CONTROL",
+  year,
+});
+
+export const setFromControl = (from: string): Action => ({
+  type: "SET_FROM_CONTROL",
+  from,
+});
+
+export const setToControl = (to: string): Action => ({
+  type: "SET_TO_CONTROL",
+  to,
+});
+
+export default {};

+ 38 - 0
app/src/context/dashboard/reducer.ts

@@ -0,0 +1,38 @@
+import { Reducer } from "react";
+import { Action } from "./actionTypes";
+
+export const defaultState = {
+  year: null,
+  from: null,
+  to: null,
+};
+
+export type State = {
+  to?: string | null;
+  from?: string | null;
+  year?: string | null;
+};
+
+const reducer: Reducer<State, Action> = (state, action) => {
+  switch (action.type) {
+    case "SET_TO_CONTROL":
+      return {
+        ...state,
+        to: action.to,
+      };
+    case "SET_FROM_CONTROL":
+      return {
+        ...state,
+        from: action.from,
+      };
+    case "SET_YEAR_CONTROL":
+      return {
+        ...state,
+        year: action.year,
+      };
+    default:
+      return state;
+  }
+};
+
+export default reducer;

+ 19 - 0
app/src/types/summary.ts

@@ -0,0 +1,19 @@
+export interface Summary {
+  station: {
+    name: string;
+    code: string;
+  };
+  from: string;
+  to: string;
+
+  // Floats
+  lt10: number;
+  gt30: number;
+  gt33: number;
+  grados_acumulados: number;
+  amplitud_termica: number;
+  precip_acumulada: number;
+
+  // Intigers
+  dias_para_igualar_temporada: number;
+}