Skip to content

Commit

Permalink
Merge pull request #115 from Carifio24/stage-states
Browse files Browse the repository at this point in the history
Add infrastructure for stage states
  • Loading branch information
Carifio24 authored Jun 14, 2024
2 parents e95caf6 + 2af8823 commit b4e349a
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 9 deletions.
53 changes: 46 additions & 7 deletions src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Student,
DummyClass,
DashboardClassGroup,
StageState,
} from "./models";

import {
Expand Down Expand Up @@ -347,35 +348,73 @@ export async function getStoryState(studentID: number, storyName: string): Promi
console.log(error);
return null;
});
return result?.story_state || null;
return result?.story_state ?? null;
}

export async function updateStoryState(studentID: number, storyName: string, newState: JSON): Promise<JSON | null> {
const query = {
student_id: studentID,
story_name: storyName,
};
let result = await StoryState.findOne({
where: query
})
.catch(error => {
console.log(error);
return null;
});

const storyData = { ...query, story_state: newState };
if (result !== null) {
result?.update(storyData);
} else {
result = await StoryState.create(storyData).catch(error => {
console.log(error);
return null;
});
}
return result?.story_state ?? null;
}

export async function getStageState(studentID: number, storyName: string, stageName: string): Promise<JSON | null> {
const result = await StageState.findOne({
where: {
student_id: studentID,
story_name: storyName
story_name: storyName,
stage_name: stageName,
}
})
.catch(error => {
console.log(error);
return null;
});
return result?.state ?? null;
}

const storyData = {
export async function updateStageState(studentID: number, storyName: string, stageName: string, newState: JSON): Promise<JSON | null> {
const query = {
student_id: studentID,
story_name: storyName,
story_state: newState
stage_name: stageName,
};
let result = await StageState.findOne({
where: query
})
.catch(error => {
console.log(error);
return null;
});

const data = { ...query, state: newState };
if (result !== null) {
result?.update(storyData);
result?.update(data);
} else {
result = await StoryState.create(storyData).catch(error => {
result = await StageState.create(data).catch(error => {
console.log(error);
return null;
});
}
return result?.story_state || null;
return result?.state ?? null;
}

export async function getClassesForEducator(educatorID: number): Promise<Class[]> {
Expand Down
3 changes: 3 additions & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Educator, initializeEducatorModel } from "./educator";
import { IgnoreStudent, initializeIgnoreStudentModel } from "./ignore_student";
import { ClassStories, initializeClassStoryModel } from "./story_class";
import { CosmicDSSession, initializeSessionModel } from "./session";
import { StageState, initializeStageStateModel } from "./stage_state";
import { StoryState, initializeStoryStateModel } from "./story_state";
import { Story, initializeStoryModel } from "./story";
import { StudentsClasses, initializeStudentClassModel } from "./student_class";
Expand All @@ -22,6 +23,7 @@ export {
DummyClass,
Educator,
IgnoreStudent,
StageState,
Story,
StoryState,
Student,
Expand All @@ -36,6 +38,7 @@ export function initializeModels(db: Sequelize) {
initializeStoryModel(db);
initializeClassStoryModel(db);
initializeDummyClassModel(db);
initializeStageStateModel(db);
initializeStoryStateModel(db);
initializeStudentClassModel(db);
initializeStudentOptionsModel(db);
Expand Down
51 changes: 51 additions & 0 deletions src/models/stage_state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Sequelize, DataTypes, Model, InferAttributes, InferCreationAttributes, CreationOptional } from "sequelize";
import { Story } from "./story";
import { Student } from "./student";

export class StageState extends Model<InferAttributes<StageState>, InferCreationAttributes<StageState>> {
declare student_id: CreationOptional<number>;
declare story_name: string;
declare stage_name: string;
declare state: JSON;
declare last_modified: CreationOptional<Date>;
}

export function initializeStageStateModel(sequelize: Sequelize) {
StageState.init({
student_id: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true,
references: {
model: Student,
key: "id"
}
},
story_name: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
references: {
model: Story,
key: "name"
}
},
stage_name: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
},
state: {
type: DataTypes.JSON,
allowNull: false
},
last_modified: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP")
}
}, {
sequelize,
engine: "InnoDB"
});
}
37 changes: 35 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {
currentVersionForQuestion,
getQuestionsForStory,
getDashboardGroupClasses,
getStageState,
updateStageState,
} from "./database";

import { getAPIKey, hasPermission } from "./authorization";
Expand Down Expand Up @@ -423,7 +425,7 @@ app.get("/story-state/:studentID/:storyName", async (req, res) => {
res.status(status).json({
student_id: studentID,
story_name: storyName,
state: state
state
});
});

Expand All @@ -437,7 +439,38 @@ app.put("/story-state/:studentID/:storyName", async (req, res) => {
res.status(status).json({
student_id: studentID,
story_name: storyName,
state: state
state
});
});

app.get("/stage-state/:studentID/:storyName/:stageName", async (req, res) => {
const params = req.params;
const studentID = Number(params.studentID);
const storyName = params.storyName;
const stageName = params.stageName;
const state = await getStageState(studentID, storyName, stageName);
const status = state !== null ? 200 : 404;
res.status(status).json({
student_id: studentID,
story_name: storyName,
stage_name: stageName,
state
});
});

app.put("/stage-state/:studentID/:storyName/:stageName", async (req, res) => {
const params = req.params;
const studentID = Number(params.studentID);
const storyName = params.storyName;
const stageName = params.stageName;
const newState = req.body;
const state = await updateStageState(studentID, storyName, stageName, newState);
const status = state !== null ? 200 : 404;
res.status(status).json({
student_id: studentID,
story_name: storyName,
stage_name: stageName,
state
});
});

Expand Down
21 changes: 21 additions & 0 deletions src/sql/create_stage_states_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CREATE TABLE StageStates (
student_id int(11) UNSIGNED NOT NULL,
story_name varchar(50) NOT NULL,
stage_name varchar(50) NOT NULL,
state JSON NOT NULL,
last_modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,

PRIMARY KEY(student_id, story_name, stage_name),
INDEX(student_id),
INDEX(story_name),
INDEX(stage_name),
FOREIGN KEY(student_id)
REFERENCES Students(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
FOREIGN KEY(story_name)
REFERENCES Stories(name)
ON UPDATE CASCADE
ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci PACK_KEYS=0;

0 comments on commit b4e349a

Please sign in to comment.