-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #104 from Carifio24/solar-eclipse-part-2
Updates to solar eclipse endpoint
- Loading branch information
Showing
11 changed files
with
984 additions
and
786 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,78 @@ | ||
import * as S from "@effect/schema/Schema"; | ||
import { cosmicdsDB } from "../../database"; | ||
import { logger } from "../../logger"; | ||
import { | ||
isArrayThatSatisfies, | ||
isNumberArray, | ||
} from "../../utils"; | ||
|
||
import { initializeModels, SolarEclipse2024Response } from "./models"; | ||
import { UpdateAttributes } from "../../utils"; | ||
import { initializeModels, SolarEclipse2024Data } from "./models"; | ||
|
||
type SolarEclipse2024UpdateAttributes = UpdateAttributes<SolarEclipse2024Data>; | ||
|
||
initializeModels(cosmicdsDB); | ||
|
||
export interface SolarEclipse2024Data { | ||
user_uuid: string; | ||
user_selected_locations: [number, number][], | ||
timestamp: Date | ||
} | ||
const LatLonArray = S.mutable(S.array(S.mutable(S.tuple(S.number, S.number)))); | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export function isValidSolarEclipseData(data: any): data is SolarEclipse2024Response { | ||
return typeof data.user_uuid === "string" && | ||
isArrayThatSatisfies(data.user_selected_locations, (arr) => { | ||
return arr.every(x => isNumberArray(x) && x.length === 2); | ||
}); | ||
} | ||
export const SolarEclipse2024Entry = S.struct({ | ||
user_uuid: S.string, | ||
user_selected_locations: LatLonArray, | ||
cloud_cover_selected_locations: LatLonArray, | ||
info_time_ms: S.optional(S.number.pipe(S.int()), { exact: true }), | ||
app_time_ms: S.optional(S.number.pipe(S.int()), { exact: true }), | ||
}); | ||
|
||
export async function submitSolarEclipse2024Response(data: SolarEclipse2024Response): Promise<SolarEclipse2024Response | null> { | ||
export const SolarEclipse2024Update = S.struct({ | ||
user_selected_locations: S.optional(LatLonArray, { exact: true }), | ||
cloud_cover_selected_locations: S.optional(LatLonArray, { exact: true }), | ||
delta_info_time_ms: S.optional(S.number.pipe(S.int()), { exact: true }), | ||
delta_app_time_ms: S.optional(S.number.pipe(S.int()), { exact: true }), | ||
}); | ||
|
||
export type SolarEclipse2024DataT = S.Schema.To<typeof SolarEclipse2024Entry>; | ||
export type SolarEclipse2024UpdateT = S.Schema.To<typeof SolarEclipse2024Update>; | ||
|
||
export async function submitSolarEclipse2024Data(data: SolarEclipse2024DataT): Promise<SolarEclipse2024Data | null> { | ||
logger.verbose(`Attempting to submit solar eclipse 2024 measurement for user ${data.user_uuid}`); | ||
|
||
const dataWithCounts = { | ||
...data, | ||
user_selected_locations_count: data.user_selected_locations.length | ||
user_selected_locations_count: data.user_selected_locations.length, | ||
cloud_cover_selected_locations_count: data.cloud_cover_selected_locations.length, | ||
}; | ||
|
||
return SolarEclipse2024Response.upsert(dataWithCounts).then(([item, _]) => item); | ||
return SolarEclipse2024Data.upsert(dataWithCounts).then(([item, _]) => item); | ||
} | ||
|
||
export async function getAllSolarEclipse2024Responses(): Promise<SolarEclipse2024Response[]> { | ||
return SolarEclipse2024Response.findAll(); | ||
export async function getAllSolarEclipse2024Data(): Promise<SolarEclipse2024Data[]> { | ||
return SolarEclipse2024Data.findAll(); | ||
} | ||
|
||
export async function getSolarEclipse2024Response(userUUID: string): Promise<SolarEclipse2024Response | null> { | ||
return SolarEclipse2024Response.findOne({ | ||
export async function getSolarEclipse2024Data(userUUID: string): Promise<SolarEclipse2024Data | null> { | ||
return SolarEclipse2024Data.findOne({ | ||
where: { user_uuid: userUUID } | ||
}); | ||
} | ||
|
||
export async function updateSolarEclipse2024Data(userUUID: string, update: SolarEclipse2024UpdateT): Promise<boolean> { | ||
const data = await SolarEclipse2024Data.findOne({ where: { user_uuid: userUUID } }); | ||
if (data === null) { | ||
return false; | ||
} | ||
const dbUpdate: SolarEclipse2024UpdateAttributes = {}; | ||
if (update.user_selected_locations) { | ||
const selected = data.user_selected_locations.concat(update.user_selected_locations); | ||
dbUpdate.user_selected_locations = selected; | ||
dbUpdate.user_selected_locations_count = selected.length; | ||
} | ||
if (update.cloud_cover_selected_locations) { | ||
const selected = data.cloud_cover_selected_locations.concat(update.cloud_cover_selected_locations); | ||
dbUpdate.cloud_cover_selected_locations = selected; | ||
dbUpdate.cloud_cover_selected_locations_count = selected.length; | ||
} | ||
if (update.delta_info_time_ms) { | ||
dbUpdate.info_time_ms = data.info_time_ms + update.delta_info_time_ms; | ||
} | ||
if (update.delta_app_time_ms) { | ||
dbUpdate.app_time_ms = data.app_time_ms + update.delta_app_time_ms; | ||
} | ||
const result = await data.update(dbUpdate); | ||
return result !== null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
import { Sequelize } from "sequelize"; | ||
import { SolarEclipse2024Response, initializeSolarEclipse2024ResponseModel } from "./eclipse_response"; | ||
import { SolarEclipse2024Data, initializeSolarEclipse2024DataModel } from "./eclipse_data"; | ||
|
||
export { | ||
SolarEclipse2024Response | ||
SolarEclipse2024Data | ||
}; | ||
|
||
export function initializeModels(db: Sequelize) { | ||
initializeSolarEclipse2024ResponseModel(db); | ||
initializeSolarEclipse2024DataModel(db); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,71 @@ | ||
import * as S from "@effect/schema/Schema"; | ||
import * as Either from "effect/Either"; | ||
import { Router } from "express"; | ||
import { getAllSolarEclipse2024Responses, getSolarEclipse2024Response, isValidSolarEclipseData, submitSolarEclipse2024Response } from "./database"; | ||
import { | ||
getAllSolarEclipse2024Data, | ||
getSolarEclipse2024Data, | ||
submitSolarEclipse2024Data, | ||
SolarEclipse2024Entry, | ||
updateSolarEclipse2024Data, | ||
SolarEclipse2024Update, | ||
} from "./database"; | ||
|
||
const router = Router(); | ||
|
||
router.put("/response", async (req, res) => { | ||
router.put("/data", async (req, res) => { | ||
const data = req.body; | ||
const valid = isValidSolarEclipseData(data); | ||
const maybe = S.decodeUnknownEither(SolarEclipse2024Entry)(data); | ||
|
||
if (!valid) { | ||
if (Either.isLeft(maybe)) { | ||
res.status(400); | ||
res.json({ error: "Malformed response submission" }); | ||
res.json({ error: "Malformed data submission" }); | ||
return; | ||
} | ||
|
||
const response = await submitSolarEclipse2024Response(data); | ||
const response = await submitSolarEclipse2024Data(maybe.right); | ||
if (response === null) { | ||
res.status(400); | ||
res.json({ error: "Error creating solar eclipse 2024 response" }); | ||
res.json({ error: "Error creating solar eclipse 2024 entry" }); | ||
return; | ||
} | ||
|
||
res.json({ response }); | ||
}); | ||
|
||
router.get("/responses", async (_req, res) => { | ||
const responses = await getAllSolarEclipse2024Responses(); | ||
router.get("/data", async (_req, res) => { | ||
const responses = await getAllSolarEclipse2024Data(); | ||
res.json({ responses }); | ||
}); | ||
|
||
router.get("/response/:userUUID", async (req, res) => { | ||
const uuid = req.params.userUUID as string; | ||
const response = await getSolarEclipse2024Response(uuid); | ||
router.get("/data/:uuid", async (req, res) => { | ||
const uuid = req.params.uuid as string; | ||
const response = await getSolarEclipse2024Data(uuid); | ||
res.json({ response }); | ||
}); | ||
|
||
router.patch("/data/:uuid", async (req, res) => { | ||
const uuid = req.params.uuid as string; | ||
const data = req.body; | ||
|
||
const maybe = S.decodeUnknownEither(SolarEclipse2024Update)(data); | ||
if (Either.isLeft(maybe)) { | ||
res.status(400).json({ error: "Malformed update submission" }); | ||
return; | ||
} | ||
|
||
const response = await getSolarEclipse2024Data(uuid); | ||
if (response === null) { | ||
res.status(404).json({ error: "Specified user data does not exist" }); | ||
return; | ||
} | ||
|
||
const success = await updateSolarEclipse2024Data(uuid, maybe.right); | ||
if (!success) { | ||
res.status(500).json({ error: "Error updating user data" }); | ||
return; | ||
} | ||
res.json({ response }); | ||
|
||
}); | ||
|
||
export default router; |
10 changes: 0 additions & 10 deletions
10
src/stories/solar-eclipse-2024/sql/create_eclipse_response_table.sql
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters