Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions apps/api/src/answer-evaluation/answer-evaluation.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const AccuracyEval = {
PERFECT: 'PERFECT',
MINOR_ERROR: 'MINOR_ERROR',
WRONG: 'WRONG',
} as const;
type AccuracyEval = (typeof AccuracyEval)[keyof typeof AccuracyEval];

const LogicEval = {
CLEAR: 'CLEAR',
WEAK: 'WEAK',
NONE: 'NONE',
} as const;
type LogicEval = (typeof LogicEval)[keyof typeof LogicEval];

const DepthEval = {
DEEP: 'DEEP',
BASIC: 'BASIC',
NONE: 'NONE',
} as const;
type DepthEval = (typeof DepthEval)[keyof typeof DepthEval];

export { AccuracyEval, LogicEval, DepthEval };
56 changes: 56 additions & 0 deletions apps/api/src/answer-evaluation/answer-evaluation.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
OneToOne,
JoinColumn,
} from 'typeorm';
import {
AccuracyEval,
LogicEval,
DepthEval,
} from './answer-evaluation.constants';
import { AnswerSubmission } from 'src/answer-submission/answer-submission.entity';

@Entity('answer_evaluations')
class AnswerEvaluation {
@PrimaryGeneratedColumn()
id: number;

@Column({ name: 'attempt_id', type: 'int' })
attemptId: number;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 attemp -> submission으로 테이블 이름이 바뀌었으니까 이것도 submissionId로 할까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오! 좋습니다


@Column({ name: 'feedback_message', type: 'text' })
feedbackMessage: string;

@Column({ name: 'detail_analysis', type: 'jsonb' })
detailAnalysis: any;

@Column({ name: 'score_details', type: 'jsonb' })
scoreDetails: any;

@Column({ name: 'accuracy_eval', type: 'enum', enum: AccuracyEval })
accuracyEval: AccuracyEval;

@Column({ name: 'logic_eval', type: 'enum', enum: LogicEval })
logicEval: LogicEval;

@Column({ name: 'depth_eval', type: 'enum', enum: DepthEval })
depthEval: DepthEval;

@Column({ name: 'has_application', type: 'boolean', default: false })
hasApplication: boolean;

@Column({ name: 'is_complete_sentence', type: 'boolean', default: false })
isCompleteSentence: boolean;

@CreateDateColumn({ name: 'created_at', type: 'timestamp' })
createdAt: Date;

@OneToOne(() => AnswerSubmission)
@JoinColumn({ name: 'attempt_id' })
submission: AnswerSubmission;
}

export { AnswerEvaluation };
20 changes: 20 additions & 0 deletions apps/api/src/answer-submission/answer-submission.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const QuizMode = {
DAILY: 'DAILY',
INTERVIEW: 'INTERVIEW',
} as const;
type QuizMode = (typeof QuizMode)[keyof typeof QuizMode];

const InputType = {
VOICE: 'VOICE',
TEXT: 'TEXT',
} as const;
type InputType = (typeof InputType)[keyof typeof InputType];

const ProcessStatus = {
PENDING: 'PENDING',
DONE: 'DONE',
FAILED: 'FAILED',
} as const;
type ProcessStatus = (typeof ProcessStatus)[keyof typeof ProcessStatus];

export { QuizMode, InputType, ProcessStatus };
75 changes: 75 additions & 0 deletions apps/api/src/answer-submission/answer-submission.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
ManyToOne,
JoinColumn,
OneToOne,
} from 'typeorm';
import {
QuizMode,
InputType,
ProcessStatus,
} from './answer-submission.constants';
import { Question } from 'src/question/question.entity';
import { AudioAsset } from 'src/audio-asset/audio-asset.entity';

@Entity('answer_submissions')
class AnswerSubmission {
@PrimaryGeneratedColumn()
id: number;

@Column({ name: 'quiz_mode', type: 'enum', enum: QuizMode })
quizMode: QuizMode;

@Column({ name: 'input_type', type: 'enum', enum: InputType })
inputType: InputType;

@Column({ name: 'raw_answer', type: 'text' })
rawAnswer: string;

@Column({ name: 'taken_time', type: 'int' })
takenTime: number;

@Column({ type: 'int', default: 0 })
score: number;

@CreateDateColumn({ name: 'submitted_at', type: 'timestamp' })
submittedAt: Date;

@Column({
name: 'stt_status',
type: 'enum',
enum: ProcessStatus,
default: ProcessStatus.PENDING,
})
sttStatus: ProcessStatus;

@Column({
name: 'evaluation_status',
type: 'enum',
enum: ProcessStatus,
default: ProcessStatus.PENDING,
})
evaluationStatus: ProcessStatus;

@Column({ name: 'user_id', type: 'int' })
userId: number;

@Column({ name: 'question_id', type: 'int' })
questionId: number;

@Column({ name: 'audio_asset_id', type: 'int' })
audioAssetId: number;

@ManyToOne(() => Question)
@JoinColumn({ name: 'question_id' })
question: Question;

@OneToOne(() => AudioAsset)
@JoinColumn({ name: 'audio_asset_id' })
audioAsset: AudioAsset;
}

export { AnswerSubmission };
27 changes: 27 additions & 0 deletions apps/api/src/audio-asset/audio-asset.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
} from 'typeorm';

@Entity('audio_assets')
class AudioAsset {
@PrimaryGeneratedColumn()
id: number;

@Column({ name: 'storage_url', type: 'text' })
storageUrl: string;

// BIGINT는 JS에서 범위 문제로 string으로 반환
@Column({ name: 'byte_size', type: 'bigint' })
byteSize: string;

@Column({ name: 'duration_ms', type: 'int' })
durationMs: number;

@CreateDateColumn({ name: 'created_at', type: 'timestamp' })
createdAt: Date;
}

export { AudioAsset };
18 changes: 18 additions & 0 deletions apps/api/src/category/category.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity('categories')
class Category {
@PrimaryGeneratedColumn()
id: number;

@Column({ type: 'varchar', length: 255 })
name: string;

@Column({ name: 'parent_id', type: 'int', nullable: true })
parentId: number | null;

@Column({ type: 'int', default: 1 })
depth: number;
}

export { Category };
45 changes: 45 additions & 0 deletions apps/api/src/question-solution/question-solution.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Question } from 'src/question/question.entity';
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
OneToOne,
JoinColumn,
} from 'typeorm';

@Entity('question_solutions')
class QuestionSolution {
@PrimaryGeneratedColumn()
id: number;

@Column({ name: 'question_id', type: 'int' })
questionId: number;

@Column({ name: 'reference_source', type: 'varchar', length: 255 })
referenceSource: string;

@Column({ name: 'standard_definition', type: 'text' })
standardDefinition: string;

@Column({ name: 'technical_mechanism', type: 'jsonb' })
technicalMechanism: any;

@Column({ name: 'key_terminology', type: 'jsonb' })
keyTerminology: any;

@Column({ name: 'practical_application', type: 'text' })
practicalApplication: string;

@Column({ name: 'common_misconceptions', type: 'text' })
commonMisconceptions: string;

@CreateDateColumn({ name: 'created_at', type: 'timestamp' })
createdAt: Date;

@OneToOne(() => Question)
@JoinColumn({ name: 'question_id' })
question: Question;
}

export { QuestionSolution };
38 changes: 38 additions & 0 deletions apps/api/src/question/question.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Category } from 'src/category/category.entity';
import {
Entity,
PrimaryGeneratedColumn,
Column,
JoinColumn,
OneToOne,
} from 'typeorm';

@Entity('questions')
class Question {
@PrimaryGeneratedColumn()
id: number;

@Column({ type: 'varchar', length: 255 })
title: string;

@Column({ type: 'text' })
content: string;

@Column({ name: 'tts_url', type: 'varchar', length: 255, nullable: true })
ttsUrl: string;

@Column({ name: 'avg_score', type: 'float', default: 0 })
avgScore: number;

@Column({ name: 'avg_importance', type: 'float', default: 0 })
avgImportance: number;

@Column({ name: 'category_id', type: 'int', nullable: true })
categoryId: number;

@OneToOne(() => Category)
@JoinColumn({ name: 'category_id' })
category: Category;
}

export { Question };
Loading