mirror of
https://github.com/samkaraca/lazuri-doviguram.git
synced 2026-04-29 17:59:51 +00:00
some experimental features introduced
This commit is contained in:
parent
89ef8b6abf
commit
21e5a40810
@ -118,6 +118,7 @@ export class DndSetting {
|
||||
};
|
||||
}
|
||||
|
||||
console.warn("no user data");
|
||||
const blanks: Map<string, Blank> = new Map(
|
||||
Array.from(answers, ([key, answer]) => [key, { answer, reply: null }])
|
||||
);
|
||||
|
||||
32
src/core/models/entities/experimental/exercise.ts
Normal file
32
src/core/models/entities/experimental/exercise.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { UserExerciseLocalRepository } from "../../repositories/interfaces/user_exercise_loca_repository";
|
||||
|
||||
export abstract class Exercise<Q> {
|
||||
constructor(readonly activityId: string, readonly questions: Q[]) {}
|
||||
|
||||
abstract get grade(): number;
|
||||
|
||||
saveLocally(userExerciseLocalRepo: UserExerciseLocalRepository) {
|
||||
userExerciseLocalRepo.saveUserActivityDataLocally({
|
||||
activityId: this.activityId,
|
||||
grade: this.grade,
|
||||
exerciseData: this,
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract createFrom(
|
||||
activityId: string,
|
||||
questions: Q[]
|
||||
): Exercise<Q>;
|
||||
|
||||
getLocalVersion(userExerciseLocalRepo: UserExerciseLocalRepository) {
|
||||
const localData = userExerciseLocalRepo.getLocalUserActivityData({
|
||||
activityId: this.activityId,
|
||||
});
|
||||
|
||||
if (localData) {
|
||||
return this.createFrom(this.activityId, localData.exerciseData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
import { Exercise } from "./exercise";
|
||||
|
||||
export class FillInBlanksQuestion {
|
||||
constructor(
|
||||
readonly id: string,
|
||||
readonly rawQuestion: Map<
|
||||
string,
|
||||
{
|
||||
type: "text" | "blank";
|
||||
value: string;
|
||||
}
|
||||
>,
|
||||
readonly replies: Map<string, string>
|
||||
) {}
|
||||
|
||||
static fromPure(
|
||||
id: string,
|
||||
rawQuestion: Map<
|
||||
string,
|
||||
{
|
||||
type: "text" | "blank";
|
||||
value: string;
|
||||
}
|
||||
>
|
||||
) {
|
||||
return new FillInBlanksQuestion(id, rawQuestion, new Map());
|
||||
}
|
||||
|
||||
static from(obj: FillInBlanksQuestion) {
|
||||
return new FillInBlanksQuestion(obj.id, obj.rawQuestion, obj.replies);
|
||||
}
|
||||
|
||||
get answers(): Map<string, { type: "blank"; value: string }> {
|
||||
return new Map(
|
||||
Array.from(this.rawQuestion).filter(
|
||||
([qKey, question]) => question.type === "blank"
|
||||
)
|
||||
) as Map<string, { type: "blank"; value: string }>;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
rawQuestion: Array.from(this.rawQuestion),
|
||||
replies: Array.from(this.replies),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class FillInBlanksExercise extends Exercise<FillInBlanksQuestion> {
|
||||
constructor(
|
||||
readonly activityId: string,
|
||||
readonly questions: FillInBlanksQuestion[]
|
||||
) {
|
||||
super(activityId, questions);
|
||||
}
|
||||
|
||||
get grade(): number {
|
||||
let correct = 0;
|
||||
let total = 0;
|
||||
|
||||
this.questions.forEach((question) => {
|
||||
question.answers.forEach((val, key) => {
|
||||
const answer = val.value;
|
||||
if (question.replies.get(key) === answer) correct++;
|
||||
total++;
|
||||
});
|
||||
});
|
||||
|
||||
return (correct / total) * 100;
|
||||
}
|
||||
|
||||
get answers() {
|
||||
return this.questions
|
||||
.map((question) => question.answers)
|
||||
.reduce(
|
||||
(accumulator, current) =>
|
||||
new Map([...Array.from(accumulator), ...Array.from(current)]),
|
||||
new Map()
|
||||
);
|
||||
}
|
||||
|
||||
protected createFrom(activityId: string, questions: FillInBlanksQuestion[]) {
|
||||
return new FillInBlanksExercise(activityId, questions);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
import { Exercise } from "./exercise";
|
||||
|
||||
export class MultipleChoiceQuestion {
|
||||
constructor(
|
||||
readonly id: string,
|
||||
readonly question: string,
|
||||
readonly choices: [string, string, string, string],
|
||||
readonly answer: 0 | 1 | 2 | 3,
|
||||
readonly reply: 0 | 1 | 2 | 3
|
||||
) {}
|
||||
|
||||
static from(obj: MultipleChoiceQuestion) {
|
||||
return new MultipleChoiceQuestion(
|
||||
obj.id,
|
||||
obj.question,
|
||||
obj.choices,
|
||||
obj.answer,
|
||||
obj.reply
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class MultipleChoiceExercise extends Exercise<MultipleChoiceQuestion> {
|
||||
constructor(
|
||||
readonly activityId: string,
|
||||
readonly questions: MultipleChoiceQuestion[]
|
||||
) {
|
||||
super(activityId, questions);
|
||||
}
|
||||
|
||||
get grade(): number {
|
||||
let correct = 0;
|
||||
let total = 0;
|
||||
|
||||
this.questions.forEach((question) => {
|
||||
if (question.answer === question.reply) correct++;
|
||||
total++;
|
||||
});
|
||||
|
||||
return (correct / total) * 100;
|
||||
}
|
||||
|
||||
protected createFrom(
|
||||
activityId: string,
|
||||
questions: MultipleChoiceQuestion[]
|
||||
) {
|
||||
return new MultipleChoiceExercise(activityId, questions);
|
||||
}
|
||||
}
|
||||
39
src/core/models/entities/experimental/simple_question.ts
Normal file
39
src/core/models/entities/experimental/simple_question.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { Exercise } from "./exercise";
|
||||
|
||||
export class SimpleQuestion {
|
||||
constructor(
|
||||
readonly id: string,
|
||||
readonly question: string,
|
||||
readonly answer: string,
|
||||
readonly reply: string
|
||||
) {}
|
||||
|
||||
static from(obj: SimpleQuestion) {
|
||||
return new SimpleQuestion(obj.id, obj.question, obj.answer, obj.reply);
|
||||
}
|
||||
}
|
||||
|
||||
export class SimpleExercise extends Exercise<SimpleQuestion> {
|
||||
constructor(
|
||||
readonly activityId: string,
|
||||
readonly questions: SimpleQuestion[]
|
||||
) {
|
||||
super(activityId, questions);
|
||||
}
|
||||
|
||||
get grade(): number {
|
||||
let correct = 0;
|
||||
let total = 0;
|
||||
|
||||
this.questions.forEach((question) => {
|
||||
if (question.answer === question.reply) correct++;
|
||||
total++;
|
||||
});
|
||||
|
||||
return (correct / total) * 100;
|
||||
}
|
||||
|
||||
protected createFrom(activityId: string, questions: SimpleQuestion[]) {
|
||||
return new SimpleExercise(activityId, questions);
|
||||
}
|
||||
}
|
||||
@ -82,6 +82,12 @@ export function DragIntoBlanksExercise({
|
||||
dndSetting.getBoardItemContainingTheLocation(
|
||||
blankKey
|
||||
);
|
||||
console.log(
|
||||
"la",
|
||||
blankKey,
|
||||
boardItemEntry,
|
||||
dndSetting.check(blankKey)
|
||||
);
|
||||
const isCorrect = dndSetting.check(blankKey);
|
||||
|
||||
return (
|
||||
|
||||
21
src/lib/models/dnd_setting/blank.ts
Normal file
21
src/lib/models/dnd_setting/blank.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Item } from "./item";
|
||||
|
||||
export class Blank {
|
||||
constructor(
|
||||
readonly id: string,
|
||||
readonly answer: string,
|
||||
readonly item: Item | null
|
||||
) {}
|
||||
|
||||
static from(obj: Blank) {
|
||||
return new Blank(obj.id, obj.answer, obj.item);
|
||||
}
|
||||
|
||||
static empty(obj: Blank) {
|
||||
return new Blank(obj.id, obj.answer, null);
|
||||
}
|
||||
|
||||
static fill(obj: Blank, item: Item) {
|
||||
return new Blank(obj.id, obj.answer, item);
|
||||
}
|
||||
}
|
||||
7
src/lib/models/dnd_setting/item.ts
Normal file
7
src/lib/models/dnd_setting/item.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export class Item {
|
||||
constructor(readonly id: string, readonly value: string) {}
|
||||
|
||||
static from(obj: Item) {
|
||||
return new Item(obj.id, obj.value);
|
||||
}
|
||||
}
|
||||
84
src/lib/models/dnd_setting/use_dnd_setting.ts
Normal file
84
src/lib/models/dnd_setting/use_dnd_setting.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { useState } from "react";
|
||||
import { Item } from "./item";
|
||||
import { Blank } from "./blank";
|
||||
|
||||
export function useDndSetting({
|
||||
boardData,
|
||||
blanksData,
|
||||
}: {
|
||||
boardData: Item[];
|
||||
blanksData: Blank[];
|
||||
}) {
|
||||
const [board, setBoard] = useState<Item[]>(boardData);
|
||||
const [blanks, setBlanks] = useState<Blank[]>(blanksData);
|
||||
const [draggedItem, setDraggedItem] = useState<Item | null>(null);
|
||||
|
||||
const startDragging = (item: Item) => {
|
||||
setDraggedItem(item);
|
||||
};
|
||||
|
||||
const stopDragging = (
|
||||
action: { type: "on-space" } | { type: "on-blank"; blankId: Blank["id"] }
|
||||
) => {
|
||||
if (!draggedItem) return;
|
||||
|
||||
// <remove dragged item from both board and blanks just in case>
|
||||
setBlanks((prev) => {
|
||||
return prev.map((blank) => {
|
||||
if (blank.item?.id === draggedItem.id) return Blank.empty(blank);
|
||||
return Blank.from(blank);
|
||||
});
|
||||
});
|
||||
setBoard((prev) => {
|
||||
return prev.filter((item) => item.id !== draggedItem.id);
|
||||
});
|
||||
// </remove dragged item from both board and blanks just in case>
|
||||
|
||||
if (action.type === "on-blank") {
|
||||
const blankIndex = blanks.findIndex(
|
||||
(blank) => blank.id === action.blankId
|
||||
);
|
||||
if (blankIndex === -1) return;
|
||||
|
||||
// <remove the predecessor if it exists>
|
||||
const blankItem = blanks[blankIndex].item;
|
||||
if (blankItem) {
|
||||
setBlanks((prev) => {
|
||||
return prev.map((blank) => {
|
||||
if (blank.item?.id === blankItem.id) return Blank.empty(blank);
|
||||
return Blank.from(blank);
|
||||
});
|
||||
});
|
||||
setBoard((prev) => [...prev, Item.from(blankItem)]);
|
||||
}
|
||||
// </remove the predecessor if it exists>
|
||||
|
||||
// place the successor finally
|
||||
setBlanks((prev) => {
|
||||
const newBlanks = [...prev];
|
||||
newBlanks[blankIndex] = Blank.fill(
|
||||
newBlanks[blankIndex],
|
||||
Item.from(draggedItem)
|
||||
);
|
||||
return newBlanks;
|
||||
});
|
||||
} else if (action.type === "on-space") {
|
||||
setBoard((prev) => {
|
||||
return [...prev, Item.from(draggedItem)];
|
||||
});
|
||||
}
|
||||
|
||||
setDraggedItem(null);
|
||||
};
|
||||
|
||||
return {
|
||||
setBoard,
|
||||
board,
|
||||
setBlanks,
|
||||
blanks,
|
||||
setDraggedItem,
|
||||
draggedItem,
|
||||
startDragging,
|
||||
stopDragging,
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user