a
This commit is contained in:
parent
9d7e8e4511
commit
92b571b0b2
16 changed files with 142 additions and 55 deletions
|
@ -5,3 +5,4 @@ indent_style = space
|
||||||
|
|
||||||
[*.{md,svelte,ts,json,rst}]
|
[*.{md,svelte,ts,json,rst}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { PrimaryKey, Sequelize, Column, Table, Model } from "sequelize-typescript";
|
|
||||||
|
|
||||||
@Table
|
|
||||||
export class Page extends Model {
|
|
||||||
@PrimaryKey
|
|
||||||
@Column
|
|
||||||
public slug: string;
|
|
||||||
|
|
||||||
@Column
|
|
||||||
public title: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Table
|
|
||||||
export class Exercise extends Model {
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function init(path: string): Promise<Sequelize> {
|
|
||||||
let sequelize = new Sequelize(`sqlite:${path}`, {
|
|
||||||
models: [Page, Exercise],
|
|
||||||
});
|
|
||||||
await sequelize.sync({ force: true });
|
|
||||||
return sequelize;
|
|
||||||
}
|
|
54
compile-database/db/page.ts
Normal file
54
compile-database/db/page.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import { PrimaryKey, Sequelize, Column, Table, Model, DataType } from "sequelize-typescript";
|
||||||
|
|
||||||
|
@Table
|
||||||
|
export class Page extends Model {
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
public slug: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
public title: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
public content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Table
|
||||||
|
export class Exercise extends Model {
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
public page_slug: string;
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
public name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Table
|
||||||
|
export class Grader extends Model {
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
public page_slug: string;
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
public exercise_name: string;
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@Column
|
||||||
|
public language: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
public style: string;
|
||||||
|
|
||||||
|
@Column(DataType.JSON)
|
||||||
|
public props: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function init(path: string): Promise<Sequelize> {
|
||||||
|
let sequelize = new Sequelize(`sqlite:${path}`, {
|
||||||
|
models: [Page, Exercise, Grader],
|
||||||
|
});
|
||||||
|
await sequelize.sync({ force: true });
|
||||||
|
return sequelize;
|
||||||
|
}
|
|
@ -4,8 +4,8 @@ import * as yaml from "js-yaml";
|
||||||
import { plainToClass } from "class-transformer";
|
import { plainToClass } from "class-transformer";
|
||||||
import { validate } from "class-validator";
|
import { validate } from "class-validator";
|
||||||
|
|
||||||
import { init, Page } from "./db";
|
import { init, Page, Exercise, Grader } from "./db/page";
|
||||||
import { Page as PageConfig, Exercise as ExerciseConfig } from "./page";
|
import { Page as PageConfig, Exercise as ExerciseConfig, Grader as GraderConfig } from "./page";
|
||||||
|
|
||||||
// TODO: configure this thru cmdline or something later
|
// TODO: configure this thru cmdline or something later
|
||||||
let materials_dir = "../material";
|
let materials_dir = "../material";
|
||||||
|
@ -17,7 +17,6 @@ let SLUG_RE = /([A-Za-z\-\_]+)/;
|
||||||
async function loadPageIntoDb(name: string): Promise<void> {
|
async function loadPageIntoDb(name: string): Promise<void> {
|
||||||
let slug_match = name.match(SLUG_RE);
|
let slug_match = name.match(SLUG_RE);
|
||||||
let slug = slug_match[0];
|
let slug = slug_match[0];
|
||||||
console.log("SLUG", slug);
|
|
||||||
|
|
||||||
// if this slug has already been loaded into the database, don't do anything
|
// if this slug has already been loaded into the database, don't do anything
|
||||||
let hasPage = await Page.count({ where: { slug }}) > 0;
|
let hasPage = await Page.count({ where: { slug }}) > 0;
|
||||||
|
@ -33,18 +32,36 @@ async function loadPageIntoDb(name: string): Promise<void> {
|
||||||
let page = new Page({
|
let page = new Page({
|
||||||
slug,
|
slug,
|
||||||
title: page_cfg.title,
|
title: page_cfg.title,
|
||||||
|
content: page_cfg.content,
|
||||||
});
|
});
|
||||||
await page.save();
|
await page.save();
|
||||||
|
|
||||||
// save exercises
|
// save exercises
|
||||||
async function loadExerciseIntoDb(ex_cfg: ExerciseConfig): Promise<void> {
|
async function loadExerciseIntoDb(ex_cfg: ExerciseConfig): Promise<void> {
|
||||||
console.log("pog", ex_cfg);
|
let exercise = new Exercise({
|
||||||
|
page_slug: slug,
|
||||||
|
name: ex_cfg.name,
|
||||||
|
});
|
||||||
|
await exercise.save();
|
||||||
|
|
||||||
|
async function loadGraderIntoDb([language, grader_cfg]: [string, GraderConfig]): Promise<void> {
|
||||||
|
let grader = new Grader({
|
||||||
|
page_slug: slug,
|
||||||
|
exercise_name: ex_cfg.name,
|
||||||
|
language,
|
||||||
|
style: grader_cfg.style,
|
||||||
|
props: grader_cfg.props,
|
||||||
|
});
|
||||||
|
await grader.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
let graders = Object.entries(ex_cfg.graders);
|
||||||
|
await Promise.all(graders.map(loadGraderIntoDb));
|
||||||
}
|
}
|
||||||
|
|
||||||
let exercises = page_cfg.exercises;
|
let exercises = page_cfg.exercises;
|
||||||
if (exercises != null) {
|
if (exercises != null) {
|
||||||
await Promise.all(exercises
|
await Promise.all(exercises.map(loadExerciseIntoDb));
|
||||||
.map(loadExerciseIntoDb));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,12 @@ export class Page {
|
||||||
public type: string;
|
public type: string;
|
||||||
|
|
||||||
public summary?: string;
|
public summary?: string;
|
||||||
|
public content: string;
|
||||||
public content?: string;
|
|
||||||
|
|
||||||
public exercises?: Exercise[];
|
public exercises?: Exercise[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Exercise {
|
export class Exercise {
|
||||||
public slug: string;
|
public name: string;
|
||||||
public description: string;
|
public description: string;
|
||||||
public graders: Grader[];
|
public graders: Grader[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
title: Functional Programming Basics
|
title: Functional Programming Basics
|
||||||
|
type: listing
|
||||||
content: |
|
content: |
|
||||||
This listing contains some of the basics of functional programming.
|
This listing contains some of the basics of functional programming.
|
||||||
|
|
||||||
|
- [Functions](page://fp-function)
|
||||||
|
|
|
@ -7,12 +7,13 @@ content: |
|
||||||
output, but in functional programming, we can usually get around this either
|
output, but in functional programming, we can usually get around this either
|
||||||
by using [tuples][1] or by [currying][2].
|
by using [tuples][1] or by [currying][2].
|
||||||
|
|
||||||
[1]: page://tuples
|
[1]: page://fp-tuples
|
||||||
[2]: page://currying
|
[2]: page://fp-currying
|
||||||
|
|
||||||
exercises:
|
exercises:
|
||||||
|
|
||||||
- name: doubleIt
|
- name: doubleIt
|
||||||
|
style: gradedProgram
|
||||||
description: |
|
description: |
|
||||||
Write a function called `doubleIt` that takes an integer and doubles it.
|
Write a function called `doubleIt` that takes an integer and doubles it.
|
||||||
|
|
||||||
|
@ -28,3 +29,13 @@ exercises:
|
||||||
(fun x -> assert ((doubleIt x) = (x * 2)))
|
(fun x -> assert ((doubleIt x) = (x * 2)))
|
||||||
(List.init 100 (fun x -> x + 1));
|
(List.init 100 (fun x -> x + 1));
|
||||||
|
|
||||||
|
- name: whichIsFunction
|
||||||
|
style: multipleChoice
|
||||||
|
description: |
|
||||||
|
Which of the following can be described as a _function_?
|
||||||
|
|
||||||
|
graders:
|
||||||
|
ocaml:
|
||||||
|
style: multipleChoice
|
||||||
|
props:
|
||||||
|
foo: bar
|
||||||
|
|
11
notes.txt
11
notes.txt
|
@ -34,3 +34,14 @@ ocaml student.cmo driver.ml
|
||||||
|
|
||||||
probably should have like $OCAMLCFLAGS in there to be able to customize each
|
probably should have like $OCAMLCFLAGS in there to be able to customize each
|
||||||
step as well
|
step as well
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
what are some good classes to start out with?
|
||||||
|
|
||||||
|
- functional programming
|
||||||
|
- ctfs?
|
||||||
|
- possibly a logic class for math
|
||||||
|
- proof class
|
||||||
|
- ML???? look into running it
|
||||||
|
- can we do reading????????????
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
{
|
{
|
||||||
|
"scripts": {
|
||||||
|
"compiledb": "cd compile-database && npm start",
|
||||||
|
"webdev": "cd web && npm run dev"
|
||||||
|
},
|
||||||
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"compile-database": "file:compile-database",
|
"compile-database": "file:compile-database",
|
||||||
"web": "file:web"
|
"web": "file:web"
|
||||||
|
|
|
@ -26,5 +26,8 @@
|
||||||
"tslib": "^2.0.0",
|
"tslib": "^2.0.0",
|
||||||
"typescript": "^4.0.0"
|
"typescript": "^4.0.0"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"sequelize-typescript": "^2.1.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="/favicon.png" />
|
<link rel="icon" href="/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Heebo:wght@300;400;700&display=swap" integrity="sha384-TIFtbbKQ3b73InoKF2MDgqFhPYGLQ1h2cnNtGUFVvvd/eRw94RvudHY4y+MMmbw4" crossorigin="anonymous">
|
||||||
|
|
||||||
%svelte.head%
|
%svelte.head%
|
||||||
<style>html, body { margin: 0; paddding: 0; }</style>
|
<style>html, body { margin: 0; paddding: 0; }</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import QuizBox from "$lib/QuizBox.svelte";
|
import MultipleChoice from "$lib/activity/MultipleChoice.svelte";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<QuizBox />
|
<MultipleChoice />
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
export default class Question {
|
|
||||||
public description: string;
|
|
||||||
public choices: Choice[];
|
|
||||||
public concepts: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Choice {
|
|
||||||
public text: string;
|
|
||||||
public correct: boolean;
|
|
||||||
};
|
|
|
@ -1,7 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type Question from "$lib/Question";
|
export let question = {
|
||||||
|
|
||||||
export let question: Question = {
|
|
||||||
description: `
|
description: `
|
||||||
what is 1 + 1?
|
what is 1 + 1?
|
||||||
`,
|
`,
|
||||||
|
@ -13,12 +11,15 @@
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// State related variables
|
||||||
let state = "ask";
|
let state = "ask";
|
||||||
|
let currentChoice;
|
||||||
let wasCorrect = false;
|
let wasCorrect = false;
|
||||||
|
|
||||||
let choose = (index: number) => {
|
let choose = (index: number) => {
|
||||||
state = "answer";
|
currentChoice = index;
|
||||||
wasCorrect = question.choices[index].correct;
|
// state = "answer";
|
||||||
|
// wasCorrect = question.choices[index].correct;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -33,6 +34,11 @@
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div class="answer-buttons">
|
||||||
|
<button>Not sure</button>
|
||||||
|
<button>Sure</button>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<small>A:</small>
|
<small>A:</small>
|
||||||
{#if wasCorrect }
|
{#if wasCorrect }
|
||||||
|
@ -47,6 +53,7 @@
|
||||||
.quiz-box {
|
.quiz-box {
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
.choices {
|
.choices {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -63,5 +70,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.answer-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
1
web/src/lib/db/index.ts
Normal file
1
web/src/lib/db/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export {};
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="footer-block">
|
<div class="footer-block">
|
||||||
<div class="footer-block-title">Eduproj</div>
|
<div class="footer-block-title">Eduproj</div>
|
||||||
<ul class="list-reset">
|
<ul class="list-reset">
|
||||||
<li>Hellosus</li>
|
<li><a href="https://git.mzhang.io/michael/eduproj" target="_blank">Source Code</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer-block">
|
<div class="footer-block">
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
$footer-height: 180px;
|
$footer-height: 180px;
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
font-family: sans-serif;
|
font-family: Heebo, sans-serif;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue