diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..3a8d38d --- /dev/null +++ b/schema.sql @@ -0,0 +1,192 @@ +-- Enable foreign key support +PRAGMA foreign_keys = ON; +PRAGMA journal_mode = WAL; +PRAGMA cache_size = -2000; +PRAGMA mmap_size = 30000000000; + + +-- Words table +CREATE TABLE expressions( + id INTEGER PRIMARY KEY AUTOINCREMENT, + spelling TEXT NOT NULL, + ipa TEXT NOT NULL, + language_id INTEGER NOT NULL, + frequency INTEGER, + type TEXT NOT NULL, + subtype TEXT, + FOREIGN KEY (language_id) REFERENCES languages(id) +); +CREATE INDEX idx_words_spelling ON expressions(spelling); +CREATE INDEX idx_words_type ON expressions(type); +CREATE INDEX idx_words_subtype ON expressions(subtype); +CREATE INDEX idx_words_language_id ON expressions(language_id); + +CREATE TABLE expression_words( + expression_id INTEGER NOT NULL, + word_id INTEGER NOT NULL, + PRIMARY KEY (expression_id, word_id), + FOREIGN KEY (word_id) REFERENCES expressions(id), + FOREIGN KEY (expression_id) REFERENCES expressions(id) +); + + +-- Languages table +CREATE TABLE languages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL +); + +-- Parts of Speech table +CREATE TABLE parts_of_speech ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL +); + +-- Categories table (for noun and verb categories) +CREATE TABLE categories ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + part_of_speech_id INTEGER NOT NULL, + FOREIGN KEY (part_of_speech_id) REFERENCES parts_of_speech(id) +); +CREATE INDEX idx_categories_name ON categories(name); +CREATE INDEX idx_categories_part_of_speech_id ON categories(part_of_speech_id); + +-- Word Categories junction table +CREATE TABLE word_categories ( + word_id INTEGER NOT NULL, + category_id INTEGER NOT NULL, + PRIMARY KEY (word_id, category_id), + FOREIGN KEY (word_id) REFERENCES words(id), + FOREIGN KEY (category_id) REFERENCES categories(id) +); +CREATE INDEX idx_word_categories_category_id ON word_categories(category_id); + +-- Example data insertion +INSERT INTO languages (name) VALUES ('en-us'); +INSERT INTO languages (name) VALUES ('th'); +INSERT INTO languages (name) VALUES ('zh-cn'); +INSERT INTO languages (name) VALUES ('zh-hk'); +INSERT INTO languages (name) VALUES ('ja-jp'); + +INSERT INTO parts_of_speech (name) VALUES ('noun'), ('verb'), ('adjective'), ('adverb'), ('pronoun'), ('adposition'), ('conjunction'), ('unknown'); + +INSERT INTO categories (name, part_of_speech_id) VALUES +('countable', 1), +('uncountable', 1), +('animate', 1), +('inanimate', 1), +('spatial', 1), +('temporal', 1), +('abstract', 1), +('noun', 1), +-- verbs +('transitive', 2), +('intransitive', 2), +('action', 2), +('mental', 2), +('auxiliar', 2), +('verb', 2), +-- adjectives +('adjective', 3), +-- adverbs +('adverb', 4), +-- pronouns +('nominative', 5), +('accusative', 5), +('genitive', 5), +-- adpositions +('preposition', 6), +('postposition', 6), +('circumposition', 6), +-- conjunctions +('conjunction', 7), +-- ? +('unknown', 8); + +-- -- Example word insertion +-- INSERT INTO words (spelling, ipa, language_id) VALUES ('book', 'bʊk', 1); + +-- -- Categorize 'book' as a countable, inanimate noun +-- INSERT INTO word_categories (word_id, category_id) +-- SELECT +-- (SELECT id FROM words WHERE spelling = 'book'), +-- id +-- FROM categories +-- WHERE name IN ('countable', 'inanimate'); + +-- -- Example verb insertion +-- INSERT INTO words (spelling, ipa, language_id) VALUES ('think','θɪŋk', 1); + +-- -- Categorize 'think' as an intransitive, mental verb +-- INSERT INTO word_categories (word_id, category_id) +-- SELECT +-- (SELECT id FROM words WHERE spelling = 'think'), +-- id +-- FROM categories +-- WHERE name IN ('intransitive', 'mental'); + + +-- Progress +CREATE TABLE users( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + creds TEXT NOT NULL +); + +-- Lessons +CREATE TABLE lessons( + id INTEGER PRIMARY KEY AUTOINCREMENT, + text TEXT NOT NULL +); +CREATE TABLE cards( + id INTEGER PRIMARY KEY AUTOINCREMENT, + text TEXT NOT NULL, + note TEXT +); +CREATE TABLE cards_expressions( + expression_id INTEGER NOT NULL, + card_id INTEGER NOT NULL, + PRIMARY KEY (card_id, expression_id), + FOREIGN KEY (card_id) REFERENCES cards(id), + FOREIGN KEY (expression_id) REFERENCES expressions(id) +); +CREATE TABLE cards_lessons( + lesson_id INTEGER, + card_id INTEGER NOT NULL, + PRIMARY KEY (card_id, lesson_id), + FOREIGN KEY (card_id) REFERENCES cards(id), + FOREIGN KEY (lesson_id) REFERENCES lessons(id) +); + +CREATE TABLE attempts( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER NOT NULL, + timestamp INTEGER NOT NULL, + card_id INTEGER NOT NULL, + good INTEGER NOT NULL, -- 0 or 1 + FOREIGN KEY (user_id) REFERENCES users(id) + FOREIGN KEY (card_id) REFERENCES cards(id) +); + +-- Index to query attempts on a specific card +CREATE INDEX idx_attempts_card ON attempts(card_id); + +-- Index to query attempts for a specific user +CREATE INDEX idx_attempts_user ON attempts(user_id); + +-- (Optional) Index to query attempts by user and resource (useful if you often query by both) +CREATE INDEX idx_attempts_user_resource ON attempts(user_id, card_id); +CREATE INDEX idx_cards_resources +ON cards_expressions(expression_id, card_id); + +-- CREATE TRIGGER IF NOT EXISTS populate_cards_resources +-- AFTER INSERT ON cards +-- FOR EACH ROW +-- BEGIN +-- -- Insert matching words into cards_resources +-- INSERT INTO cards_expressions(card_id, expression_id) +-- SELECT NEW.id, w.id +-- FROM expressions w +-- WHERE NEW.text LIKE '%' || w.spelling || '%'; +-- END; diff --git a/server/db.ts b/server/db.ts index 059d877..ce7645d 100644 --- a/server/db.ts +++ b/server/db.ts @@ -1,5 +1,5 @@ -import { Database } from 'bun:sqlite'; -import { wordFactorial } from './utils'; +import { Database } from "bun:sqlite"; +import { wordFactorial } from "./utils"; // read @@ -42,13 +42,29 @@ export function fetchLessons(db: Database, count: number, page: number) { const offset = (p - 1) * count; const queryString = ` SELECT - l.id, l.text as ltext, cards.text as ctext, cards.note as cnote, cards.id as cid - FROM cards_lessons cl - JOIN lessons l ON l.id = cl.lesson_id + l.id, l.text as ltext, cards.text as ctext, cards.note as cnote, cards.id as cid, + e.spelling, e.ipa, e.frequency, e.id as eid, + GROUP_CONCAT(cg.name, ',') AS category + FROM expressions e + JOIN cards_expressions ce ON e.id = ce.expression_id JOIN cards ON cards.id = cl.card_id + JOIN cards_lessons cl ON cl.card_id = cards.id + JOIN lessons l ON l.id = cl.lesson_id + JOIN expressions e ON e.id = ce.expression_id + JOIN word_categories wc ON wc.word_id = e.id + JOIN categories cg ON cg.id = wc.category_id LIMIT $count OFFSET $offset `; + // const queryString = ` + // SELECT + // l.id, l.text as ltext, cards.text as ctext, cards.note as cnote, cards.id as cid + // FROM cards_lessons cl + // JOIN lessons l ON l.id = cl.lesson_id + // JOIN cards ON cards.id = cl.card_id + // LIMIT $count + // OFFSET $offset + // `; const query = db.query(queryString); const res = query.all({ count, offset }); return res; @@ -58,12 +74,19 @@ export function fetchLessons(db: Database, count: number, page: number) { export function fetchLesson(db: Database, lesson: number) { const queryString = ` SELECT - l.id, l.text, cards.text, cards.note, cards.id as cid + l.id, l.text, cards.text, cards.note, cards.id as cid, + spelling, ipa, frequency, e.id as eid, + GROUP_CONCAT(cg.name, ',') AS category FROM cards_lessons cl JOIN lessons l ON l.id = cl.lesson_id JOIN cards ON cards.id = lc.card_id + JOIN cards_expressions ce ON cards.id = ce.card_id + JOIN expressions e ON e.id = ce.expression_id + JOIN word_categories wc ON wc.word_id = e.id + JOIN categories cg ON cg.id = wc.category_id WHERE l.id = $lesson `; + console.log(queryString); const query = db.query(queryString); return query.all({ lesson }); } @@ -102,7 +125,7 @@ export function addCard( INTO cards(text, note) VALUES($text, $note) `); - const params = { text, note }; + const params = { text, note, spel: text }; const res = query.run(params); const cid = res.lastInsertRowid; const wquery = db.query(` @@ -117,10 +140,10 @@ export function addCard( for (const pair of pairs) wquery.run(pair); }); const words = text - .replace(/[^\w\s]/g, '') - .replace(/\s+/g, ' ') + .replace(/[^\w\s]/g, "") + .replace(/\s+/g, " ") .trim() - .split(' '); + .split(" "); const combinations = wordFactorial(words); const richWords = combinations.map((spelling) => { return { spelling, cid }; @@ -173,58 +196,58 @@ export function addCat(db: Database, wordId: number | bigint, domain: string) { WHERE name = $category )) `; - const category = domains[domain] || 'unknown'; + const category = domains[domain] || "unknown"; const query = db.query(queryString); const res = query.run({ wordId, category }); return res.lastInsertRowid; } const domains: Record = { - 'adj.all': 'adjective', - 'adj.pert': 'adjective', - 'adj.ppl': 'adjective', - 'adv.all': 'adverb', - 'noun.Tops': '', - 'noun.act': 'abstract', - 'noun.animal': 'animate', - 'noun.artifact': 'inanimate', - 'noun.attribute': 'abstract', - 'noun.body': 'inanimate', - 'noun.cognition': 'abstract', - 'noun.communication': 'abstract', - 'noun.event': 'abstract', - 'noun.feeling': 'abstract', - 'noun.food': 'inanimate', - 'noun.group': 'noun', - 'noun.location': 'spatial', - 'noun.motive': 'abstract', - 'noun.object': 'inanimate', - 'noun.person': 'animate', - 'noun.phenomenon': 'abstract', - 'noun.plant': 'noun', - 'noun.possession': 'noun', - 'noun.process': 'noun', - 'noun.quantity': 'uncountable', - 'noun.relation': 'noun', - 'noun.shape': 'noun', - 'noun.state': 'noun', - 'noun.substance': 'uncountable', - 'noun.time': 'temporal', - 'verb.body': 'verb', - 'verb.change': 'verb', - 'verb.cognition': 'verb', - 'verb.communication': 'verb', - 'verb.competition': 'verb', - 'verb.consumption': 'verb', - 'verb.contact': 'verb', - 'verb.creation': 'verb', - 'verb.emotion': 'mental', - 'verb.motion': 'verb', - 'verb.perception': 'mental', - 'verb.possession': 'verb', - 'verb.social': 'verb', - 'verb.stative': 'verb', - 'verb.weather': 'verb', + "adj.all": "adjective", + "adj.pert": "adjective", + "adj.ppl": "adjective", + "adv.all": "adverb", + "noun.Tops": "", + "noun.act": "abstract", + "noun.animal": "animate", + "noun.artifact": "inanimate", + "noun.attribute": "abstract", + "noun.body": "inanimate", + "noun.cognition": "abstract", + "noun.communication": "abstract", + "noun.event": "abstract", + "noun.feeling": "abstract", + "noun.food": "inanimate", + "noun.group": "noun", + "noun.location": "spatial", + "noun.motive": "abstract", + "noun.object": "inanimate", + "noun.person": "animate", + "noun.phenomenon": "abstract", + "noun.plant": "noun", + "noun.possession": "noun", + "noun.process": "noun", + "noun.quantity": "uncountable", + "noun.relation": "noun", + "noun.shape": "noun", + "noun.state": "noun", + "noun.substance": "uncountable", + "noun.time": "temporal", + "verb.body": "verb", + "verb.change": "verb", + "verb.cognition": "verb", + "verb.communication": "verb", + "verb.competition": "verb", + "verb.consumption": "verb", + "verb.contact": "verb", + "verb.creation": "verb", + "verb.emotion": "mental", + "verb.motion": "verb", + "verb.perception": "mental", + "verb.possession": "verb", + "verb.social": "verb", + "verb.stative": "verb", + "verb.weather": "verb", }; export function addFrequency( db: Database, @@ -238,5 +261,5 @@ export function addFrequency( `; const query = db.query(queryString); const res = query.run({ spelling, frequency }); - console.log(res, 'added frequency'); + console.log(res, "added frequency"); } diff --git a/server/seeding.ts b/server/seeding.ts index d9d6533..38bb881 100644 --- a/server/seeding.ts +++ b/server/seeding.ts @@ -1,11 +1,10 @@ -import { Database } from 'bun:sqlite'; -import { addCard, addCat, addFrequency, addLesson, addWord } from './db'; -import Wordnet from 'en-wordnet'; +import { Database } from "bun:sqlite"; +import { addCard, addCat, addFrequency, addLesson, addWord } from "./db"; // const db = new Database('../db/data.db'); -const db = new Database('../db/data.db', { strict: true }); -const wndb = new Database('../datasets/en-wordnet/data.sqlite'); -db.exec('PRAGMA journal_mode = WAL;'); +const db = new Database("../db/data.db", { strict: true }); +const wndb = new Database("../datasets/en-wordnet/data.sqlite"); +db.exec("PRAGMA journal_mode = WAL;"); const SYMBOL_REGEX = new RegExp(/[\W\d]/); @@ -33,22 +32,22 @@ const SYMBOL_REGEX = new RegExp(/[\W\d]/); // } async function englishFreq() { - const file = Bun.file('../datasets/unigram_freq.csv'); + const file = Bun.file("../datasets/unigram_freq.csv"); const s = file.stream(); const reader = s.getReader(); const decoder = new TextDecoder(); - let leftover = ''; + let leftover = ""; let lineCount = 0; while (true) { const { value, done } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); - const lines = (leftover + chunk).split('\n'); + const lines = (leftover + chunk).split("\n"); // Process each line except the last (which might be incomplete) for (const line of lines.slice(0, -1)) { lineCount++; - const [spelling, _frequency] = line.split(','); + const [spelling, _frequency] = line.split(","); addFrequency(db, spelling, lineCount); } @@ -77,12 +76,12 @@ function englishIPA() { domainname: string; }> = query.all() as any; for (const r of res) { - console.log('adding word', r); + console.log("adding word", r); // if (r.word === 'abrasive') throw new Error('stop right here'); - const split = r.word.split(' '); - const type = split.length > 1 ? 'expression' : 'word'; + const split = r.word.split(" "); + const type = split.length > 1 ? "expression" : "word"; const subtype = null; - const wordid = addWord(db, r.word, r.pronunciation, 'en-us', type, subtype); + const wordid = addWord(db, r.word, r.pronunciation, "en-us", type, subtype); addCat(db, wordid, r.domainname); } } @@ -107,37 +106,37 @@ function englishIPA() { // } function englishCards() { - const lesson_id = addLesson(db, 'First Lesson, some easy stuff'); + const lesson_id = addLesson(db, "First Lesson, some easy stuff"); const texts = [ - 'I', - 'friend', - 'my friend', - 'you', - 'your friend', + "I", + "friend", + "my friend", + "you", + "your friend", "my friends' friend", - 'you are my friend', - 'I am your friend', - 'your friend is my friend', - 'my friend is your friend', - 'he is my friend', - 'this is mine', - 'this is yours', + "you are my friend", + "I am your friend", + "your friend is my friend", + "my friend is your friend", + "he is my friend", + "this is mine", + "this is yours", "this is my friends'", - 'no', - 'you are not my friend', - 'this is not yours', - 'your friend is not my friend', - 'that is mine', - 'this is mine, that is yours', - 'he is not your friend', - 'no, I am not', - 'that is not me', + "no", + "you are not my friend", + "this is not yours", + "your friend is not my friend", + "that is mine", + "this is mine, that is yours", + "he is not your friend", + "no, I am not", + "that is not me", "that is not mine, that is my friends'", ]; for (const text of texts) { addCard(db, lesson_id, text); } } -englishIPA(); -englishFreq(); +// englishIPA(); +// englishFreq(); englishCards(); diff --git a/server/server.ts b/server/server.ts index f2fc5a4..8582117 100644 --- a/server/server.ts +++ b/server/server.ts @@ -1,23 +1,23 @@ -import { Database } from 'bun:sqlite'; +import { Database } from "bun:sqlite"; import { addUser, fetchCard, fetchLesson, fetchLessons, fetchResource, -} from './db'; +} from "./db"; -const db = new Database('../db/data.db', { strict: true }); -db.exec('PRAGMA journal_mode = WAL;'); +const db = new Database("../db/data.db", { strict: true }); +db.exec("PRAGMA journal_mode = WAL;"); Bun.serve({ fetch(req) { const url = new URL(req.url); - console.log(url.pathname, 'url'); + console.log(url.pathname, "url"); const user = parseUser(req); - if (req.method === 'POST' && url.pathname === '/api') + if (req.method === "POST" && url.pathname === "/api") return handlePost(req, user, url); - if (req.method === 'GET' && url.pathname.startsWith('/api')) + if (req.method === "GET" && url.pathname.startsWith("/api")) return handleGet(req, user, url); return serveStatic(url); }, @@ -29,27 +29,27 @@ function parseUser(req: Request): number { } async function serveStatic(url: URL) { - const filename = url.pathname === '/' ? '/index.html' : url.pathname; - const headers = { 'Content-type': 'text/html' }; + const filename = url.pathname === "/" ? "/index.html" : url.pathname; + const headers = { "Content-type": "text/html" }; const opts = { headers }; try { const file = await Bun.file(`../ui/${filename}`).bytes(); return new Response(file, opts); } catch (_) { - return new Response('404!'); + return new Response("404!"); } } async function handleGet(_req: Request, user: number, url: URL) { - if (url.pathname === '/api/resource') return handleGetExpresion(user, url); - if (url.pathname === '/api/card') return handleGetCard(user, url); - if (url.pathname === '/api/lesson') return handleGetLesson(user, url); - if (url.pathname === '/api/lessons') return handleGetLessons(user, url); - else return new Response('huh'); + if (url.pathname === "/api/resource") return handleGetExpresion(user, url); + if (url.pathname === "/api/card") return handleGetCard(user, url); + if (url.pathname === "/api/lesson") return handleGetLesson(user, url); + if (url.pathname === "/api/lessons") return handleGetLessons(user, url); + else return new Response("huh"); } function handleGetExpresion(user: number, url: URL) { const params = new URLSearchParams(url.search); - const expression = params.get('exp'); + const expression = params.get("exp"); const data = fetchResource(db, expression!); return Response.json({ ok: data }); } @@ -70,20 +70,21 @@ type LessonsDBType = { }; function handleGetLesson(user: number, url: URL) { const params = new URLSearchParams(url.search); - const lesson = params.get('lesson'); + const lesson = params.get("lesson"); const data = fetchLesson(db, Number(lesson!)); return Response.json({ ok: data }); } function handleGetCard(user: number, url: URL) { const params = new URLSearchParams(url.search); - const card = params.get('card'); + const card = params.get("card"); const data = fetchCard(db, Number(card), user); return Response.json({ ok: data }); } function handleGetLessons(user: number, url: URL) { const params = new URLSearchParams(url.search); - const page = params.get('page') || '0'; + const page = params.get("page") || "0"; const data: LessonsDBType[] = fetchLessons(db, 20, Number(page)) as any; + console.log(data, "fetchlessons"); const lessons = data.reduce((acc: LessonsType, item: LessonsDBType) => { let cur = acc[item.id] || { id: item.id, text: item.ltext, cards: [] }; const cards = [ @@ -93,18 +94,18 @@ function handleGetLessons(user: number, url: URL) { const def = { ...cur, cards }; return { ...acc, [item.id]: def }; }, {} as LessonsType); - console.log(lessons, 'lesons'); + console.log(lessons, "lesons"); return Response.json({ ok: lessons }); } async function handlePost(req: Request, user: number, url: URL) { const data = await req.json(); - if (url.pathname === '/api/user') return handlePostUser(data); - else return new Response('huh'); + if (url.pathname === "/api/user") return handlePostUser(data); + else return new Response("huh"); } // https://bun.sh/guides/http/server type PostUser = { name: string; creds: string }; function handlePostUser(user: PostUser) { addUser(db, user.name, user.creds); - return new Response('ok'); + return new Response("ok"); } diff --git a/ui/elm.js b/ui/elm.js index ea8ab8e..0b63570 100644 --- a/ui/elm.js +++ b/ui/elm.js @@ -4547,6 +4547,23 @@ function _Http_track(router, xhr, tracker) }); } +function _Url_percentEncode(string) +{ + return encodeURIComponent(string); +} + +function _Url_percentDecode(string) +{ + try + { + return $elm$core$Maybe$Just(decodeURIComponent(string)); + } + catch (e) + { + return $elm$core$Maybe$Nothing; + } +} + var _Bitwise_and = F2(function(a, b) { @@ -4582,24 +4599,7 @@ var _Bitwise_shiftRightZfBy = F2(function(offset, a) { return a >>> offset; }); - - -function _Url_percentEncode(string) -{ - return encodeURIComponent(string); -} - -function _Url_percentDecode(string) -{ - try - { - return $elm$core$Maybe$Just(decodeURIComponent(string)); - } - catch (e) - { - return $elm$core$Maybe$Nothing; - } -}var $author$project$Types$LinkClicked = function (a) { +var $author$project$Types$LinkClicked = function (a) { return {$: 'LinkClicked', a: a}; }; var $author$project$Types$UrlChanged = function (a) { @@ -6303,10 +6303,303 @@ var $author$project$Api$fetchLessons = $elm$http$Http$get( $author$project$Api$serverResponseDecoder($author$project$Api$lessonsDecoder)), url: 'http://localhost:3000/api/lessons' }); +var $author$project$Types$NotFound = {$: 'NotFound'}; +var $elm$url$Url$Parser$State = F5( + function (visited, unvisited, params, frag, value) { + return {frag: frag, params: params, unvisited: unvisited, value: value, visited: visited}; + }); +var $elm$url$Url$Parser$getFirstMatch = function (states) { + getFirstMatch: + while (true) { + if (!states.b) { + return $elm$core$Maybe$Nothing; + } else { + var state = states.a; + var rest = states.b; + var _v1 = state.unvisited; + if (!_v1.b) { + return $elm$core$Maybe$Just(state.value); + } else { + if ((_v1.a === '') && (!_v1.b.b)) { + return $elm$core$Maybe$Just(state.value); + } else { + var $temp$states = rest; + states = $temp$states; + continue getFirstMatch; + } + } + } + } +}; +var $elm$url$Url$Parser$removeFinalEmpty = function (segments) { + if (!segments.b) { + return _List_Nil; + } else { + if ((segments.a === '') && (!segments.b.b)) { + return _List_Nil; + } else { + var segment = segments.a; + var rest = segments.b; + return A2( + $elm$core$List$cons, + segment, + $elm$url$Url$Parser$removeFinalEmpty(rest)); + } + } +}; +var $elm$url$Url$Parser$preparePath = function (path) { + var _v0 = A2($elm$core$String$split, '/', path); + if (_v0.b && (_v0.a === '')) { + var segments = _v0.b; + return $elm$url$Url$Parser$removeFinalEmpty(segments); + } else { + var segments = _v0; + return $elm$url$Url$Parser$removeFinalEmpty(segments); + } +}; +var $elm$url$Url$Parser$addToParametersHelp = F2( + function (value, maybeList) { + if (maybeList.$ === 'Nothing') { + return $elm$core$Maybe$Just( + _List_fromArray( + [value])); + } else { + var list = maybeList.a; + return $elm$core$Maybe$Just( + A2($elm$core$List$cons, value, list)); + } + }); +var $elm$url$Url$percentDecode = _Url_percentDecode; +var $elm$url$Url$Parser$addParam = F2( + function (segment, dict) { + var _v0 = A2($elm$core$String$split, '=', segment); + if ((_v0.b && _v0.b.b) && (!_v0.b.b.b)) { + var rawKey = _v0.a; + var _v1 = _v0.b; + var rawValue = _v1.a; + var _v2 = $elm$url$Url$percentDecode(rawKey); + if (_v2.$ === 'Nothing') { + return dict; + } else { + var key = _v2.a; + var _v3 = $elm$url$Url$percentDecode(rawValue); + if (_v3.$ === 'Nothing') { + return dict; + } else { + var value = _v3.a; + return A3( + $elm$core$Dict$update, + key, + $elm$url$Url$Parser$addToParametersHelp(value), + dict); + } + } + } else { + return dict; + } + }); +var $elm$url$Url$Parser$prepareQuery = function (maybeQuery) { + if (maybeQuery.$ === 'Nothing') { + return $elm$core$Dict$empty; + } else { + var qry = maybeQuery.a; + return A3( + $elm$core$List$foldr, + $elm$url$Url$Parser$addParam, + $elm$core$Dict$empty, + A2($elm$core$String$split, '&', qry)); + } +}; +var $elm$url$Url$Parser$parse = F2( + function (_v0, url) { + var parser = _v0.a; + return $elm$url$Url$Parser$getFirstMatch( + parser( + A5( + $elm$url$Url$Parser$State, + _List_Nil, + $elm$url$Url$Parser$preparePath(url.path), + $elm$url$Url$Parser$prepareQuery(url.query), + url.fragment, + $elm$core$Basics$identity))); + }); +var $author$project$Types$LessonR = F2( + function (a, b) { + return {$: 'LessonR', a: a, b: b}; + }); +var $author$project$Types$Root = {$: 'Root'}; +var $elm$url$Url$Parser$Parser = function (a) { + return {$: 'Parser', a: a}; +}; +var $elm$url$Url$Parser$custom = F2( + function (tipe, stringToSomething) { + return $elm$url$Url$Parser$Parser( + function (_v0) { + var value = _v0.value; + var frag = _v0.frag; + var params = _v0.params; + var unvisited = _v0.unvisited; + var visited = _v0.visited; + if (!unvisited.b) { + return _List_Nil; + } else { + var next = unvisited.a; + var rest = unvisited.b; + var _v2 = stringToSomething(next); + if (_v2.$ === 'Just') { + var nextValue = _v2.a; + return _List_fromArray( + [ + A5( + $elm$url$Url$Parser$State, + A2($elm$core$List$cons, next, visited), + rest, + params, + frag, + value(nextValue)) + ]); + } else { + return _List_Nil; + } + } + }); + }); +var $elm$url$Url$Parser$int = A2($elm$url$Url$Parser$custom, 'NUMBER', $elm$core$String$toInt); +var $elm$url$Url$Parser$mapState = F2( + function (func, _v0) { + var value = _v0.value; + var frag = _v0.frag; + var params = _v0.params; + var unvisited = _v0.unvisited; + var visited = _v0.visited; + return A5( + $elm$url$Url$Parser$State, + visited, + unvisited, + params, + frag, + func(value)); + }); +var $elm$url$Url$Parser$map = F2( + function (subValue, _v0) { + var parseArg = _v0.a; + return $elm$url$Url$Parser$Parser( + function (_v1) { + var value = _v1.value; + var frag = _v1.frag; + var params = _v1.params; + var unvisited = _v1.unvisited; + var visited = _v1.visited; + return A2( + $elm$core$List$map, + $elm$url$Url$Parser$mapState(value), + parseArg( + A5($elm$url$Url$Parser$State, visited, unvisited, params, frag, subValue))); + }); + }); +var $elm$core$List$append = F2( + function (xs, ys) { + if (!ys.b) { + return xs; + } else { + return A3($elm$core$List$foldr, $elm$core$List$cons, ys, xs); + } + }); +var $elm$core$List$concat = function (lists) { + return A3($elm$core$List$foldr, $elm$core$List$append, _List_Nil, lists); +}; +var $elm$core$List$concatMap = F2( + function (f, list) { + return $elm$core$List$concat( + A2($elm$core$List$map, f, list)); + }); +var $elm$url$Url$Parser$oneOf = function (parsers) { + return $elm$url$Url$Parser$Parser( + function (state) { + return A2( + $elm$core$List$concatMap, + function (_v0) { + var parser = _v0.a; + return parser(state); + }, + parsers); + }); +}; +var $elm$url$Url$Parser$s = function (str) { + return $elm$url$Url$Parser$Parser( + function (_v0) { + var value = _v0.value; + var frag = _v0.frag; + var params = _v0.params; + var unvisited = _v0.unvisited; + var visited = _v0.visited; + if (!unvisited.b) { + return _List_Nil; + } else { + var next = unvisited.a; + var rest = unvisited.b; + return _Utils_eq(next, str) ? _List_fromArray( + [ + A5( + $elm$url$Url$Parser$State, + A2($elm$core$List$cons, next, visited), + rest, + params, + frag, + value) + ]) : _List_Nil; + } + }); +}; +var $elm$url$Url$Parser$slash = F2( + function (_v0, _v1) { + var parseBefore = _v0.a; + var parseAfter = _v1.a; + return $elm$url$Url$Parser$Parser( + function (state) { + return A2( + $elm$core$List$concatMap, + parseAfter, + parseBefore(state)); + }); + }); +var $elm$url$Url$Parser$top = $elm$url$Url$Parser$Parser( + function (state) { + return _List_fromArray( + [state]); + }); +var $author$project$Router$routeParser = $elm$url$Url$Parser$oneOf( + _List_fromArray( + [ + A2($elm$url$Url$Parser$map, $author$project$Types$Root, $elm$url$Url$Parser$top), + A2( + $elm$url$Url$Parser$map, + $author$project$Types$LessonR, + A2( + $elm$url$Url$Parser$slash, + $elm$url$Url$Parser$s('lesson'), + A2($elm$url$Url$Parser$slash, $elm$url$Url$Parser$int, $elm$url$Url$Parser$int))) + ])); +var $elm$core$Maybe$withDefault = F2( + function (_default, maybe) { + if (maybe.$ === 'Just') { + var value = maybe.a; + return value; + } else { + return _default; + } + }); +var $author$project$Router$parseUrl = function (url) { + return A2( + $elm$core$Maybe$withDefault, + $author$project$Types$NotFound, + A2($elm$url$Url$Parser$parse, $author$project$Router$routeParser, url)); +}; var $author$project$Main$sampleLessons = $elm$core$Dict$fromList(_List_Nil); var $author$project$Main$initialState = F2( function (url, key) { - return {isLoading: false, key: key, lessons: $author$project$Main$sampleLessons, url: url}; + var route = $author$project$Router$parseUrl(url); + return {isLoading: false, key: key, lessons: $author$project$Main$sampleLessons, route: route}; }); var $elm$core$Debug$log = _Debug_log; var $author$project$Main$init = F3( @@ -6424,14 +6717,14 @@ var $author$project$Main$update = F2( } default: var url = msg.a; + var newRoute = $author$project$Router$parseUrl(url); return _Utils_Tuple2( _Utils_update( model, - {url: url}), + {route: newRoute}), $elm$core$Platform$Cmd$none); } }); -var $author$project$Router$NotFound = {$: 'NotFound'}; var $author$project$Types$FetchLesson = function (a) { return {$: 'FetchLesson', a: a}; }; @@ -6643,15 +6936,6 @@ var $mdgriffith$elm_ui$Internal$Model$transformClass = function (transform) { 'tfrm-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(tx) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(ty) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(tz) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(sx) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(sy) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(sz) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(ox) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(oy) + ('-' + ($mdgriffith$elm_ui$Internal$Model$floatClass(oz) + ('-' + $mdgriffith$elm_ui$Internal$Model$floatClass(angle)))))))))))))))))))); } }; -var $elm$core$Maybe$withDefault = F2( - function (_default, maybe) { - if (maybe.$ === 'Just') { - var value = maybe.a; - return value; - } else { - return _default; - } - }); var $mdgriffith$elm_ui$Internal$Model$getStyleName = function (style) { switch (style.$) { case 'Shadows': @@ -6995,22 +7279,6 @@ var $mdgriffith$elm_ui$Internal$Style$CenterY = {$: 'CenterY'}; var $mdgriffith$elm_ui$Internal$Style$Top = {$: 'Top'}; var $mdgriffith$elm_ui$Internal$Style$alignments = _List_fromArray( [$mdgriffith$elm_ui$Internal$Style$Top, $mdgriffith$elm_ui$Internal$Style$Bottom, $mdgriffith$elm_ui$Internal$Style$Right, $mdgriffith$elm_ui$Internal$Style$Left, $mdgriffith$elm_ui$Internal$Style$CenterX, $mdgriffith$elm_ui$Internal$Style$CenterY]); -var $elm$core$List$append = F2( - function (xs, ys) { - if (!ys.b) { - return xs; - } else { - return A3($elm$core$List$foldr, $elm$core$List$cons, ys, xs); - } - }); -var $elm$core$List$concat = function (lists) { - return A3($elm$core$List$foldr, $elm$core$List$append, _List_Nil, lists); -}; -var $elm$core$List$concatMap = F2( - function (f, list) { - return $elm$core$List$concat( - A2($elm$core$List$map, f, list)); - }); var $mdgriffith$elm_ui$Internal$Style$contentName = function (desc) { switch (desc.a.$) { case 'Top': @@ -12250,6 +12518,37 @@ var $mdgriffith$elm_ui$Internal$Model$Fill = function (a) { return {$: 'Fill', a: a}; }; var $mdgriffith$elm_ui$Element$fill = $mdgriffith$elm_ui$Internal$Model$Fill(1); +var $mdgriffith$elm_ui$Internal$Model$InFront = {$: 'InFront'}; +var $mdgriffith$elm_ui$Internal$Model$Nearby = F2( + function (a, b) { + return {$: 'Nearby', a: a, b: b}; + }); +var $mdgriffith$elm_ui$Internal$Model$NoAttribute = {$: 'NoAttribute'}; +var $mdgriffith$elm_ui$Element$createNearby = F2( + function (loc, element) { + if (element.$ === 'Empty') { + return $mdgriffith$elm_ui$Internal$Model$NoAttribute; + } else { + return A2($mdgriffith$elm_ui$Internal$Model$Nearby, loc, element); + } + }); +var $mdgriffith$elm_ui$Element$inFront = function (element) { + return A2($mdgriffith$elm_ui$Element$createNearby, $mdgriffith$elm_ui$Internal$Model$InFront, element); +}; +var $author$project$Lessonpage$cardNote = function (ms) { + if (ms.$ === 'Just') { + var txt = ms.a; + return A2( + $mdgriffith$elm_ui$Element$el, + _List_Nil, + $mdgriffith$elm_ui$Element$text(txt)); + } else { + return A2( + $mdgriffith$elm_ui$Element$el, + _List_Nil, + $mdgriffith$elm_ui$Element$text('')); + } +}; var $mdgriffith$elm_ui$Internal$Model$AsColumn = {$: 'AsColumn'}; var $mdgriffith$elm_ui$Internal$Model$asColumn = $mdgriffith$elm_ui$Internal$Model$AsColumn; var $mdgriffith$elm_ui$Element$column = F2( @@ -12270,6 +12569,230 @@ var $mdgriffith$elm_ui$Element$column = F2( attrs))), $mdgriffith$elm_ui$Internal$Model$Unkeyed(children)); }); +var $author$project$Lessonpage$cardView = function (card) { + return A2( + $mdgriffith$elm_ui$Element$column, + _List_Nil, + _List_fromArray( + [ + A2( + $mdgriffith$elm_ui$Element$el, + _List_Nil, + $mdgriffith$elm_ui$Element$text(card.text)), + $author$project$Lessonpage$cardNote(card.note) + ])); +}; +var $elm$core$List$drop = F2( + function (n, list) { + drop: + while (true) { + if (n <= 0) { + return list; + } else { + if (!list.b) { + return list; + } else { + var x = list.a; + var xs = list.b; + var $temp$n = n - 1, + $temp$list = xs; + n = $temp$n; + list = $temp$list; + continue drop; + } + } + } + }); +var $elm$core$List$head = function (list) { + if (list.b) { + var x = list.a; + var xs = list.b; + return $elm$core$Maybe$Just(x); + } else { + return $elm$core$Maybe$Nothing; + } +}; +var $elm_community$list_extra$List$Extra$getAt = F2( + function (idx, xs) { + return (idx < 0) ? $elm$core$Maybe$Nothing : $elm$core$List$head( + A2($elm$core$List$drop, idx, xs)); + }); +var $author$project$Lessonpage$notFound = A2( + $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [$mdgriffith$elm_ui$Element$centerX]), + $mdgriffith$elm_ui$Element$text('404')); +var $author$project$Lessonpage$lessonView = F2( + function (lesson, cid) { + var _v0 = A2($elm_community$list_extra$List$Extra$getAt, cid, lesson.cards); + if (_v0.$ === 'Just') { + var c = _v0.a; + return $author$project$Lessonpage$cardView(c); + } else { + return $author$project$Lessonpage$notFound; + } + }); +var $mdgriffith$elm_ui$Internal$Model$Right = {$: 'Right'}; +var $mdgriffith$elm_ui$Element$alignRight = $mdgriffith$elm_ui$Internal$Model$AlignX($mdgriffith$elm_ui$Internal$Model$Right); +var $mdgriffith$elm_ui$Internal$Model$Px = function (a) { + return {$: 'Px', a: a}; +}; +var $mdgriffith$elm_ui$Element$px = $mdgriffith$elm_ui$Internal$Model$Px; +var $mdgriffith$elm_ui$Internal$Model$AsRow = {$: 'AsRow'}; +var $mdgriffith$elm_ui$Internal$Model$asRow = $mdgriffith$elm_ui$Internal$Model$AsRow; +var $mdgriffith$elm_ui$Element$row = F2( + function (attrs, children) { + return A4( + $mdgriffith$elm_ui$Internal$Model$element, + $mdgriffith$elm_ui$Internal$Model$asRow, + $mdgriffith$elm_ui$Internal$Model$div, + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Internal$Model$htmlClass($mdgriffith$elm_ui$Internal$Style$classes.contentLeft + (' ' + $mdgriffith$elm_ui$Internal$Style$classes.contentCenterY)), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$shrink), + A2( + $elm$core$List$cons, + $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$shrink), + attrs))), + $mdgriffith$elm_ui$Internal$Model$Unkeyed(children)); + }); +var $mdgriffith$elm_ui$Internal$Model$SpacingStyle = F3( + function (a, b, c) { + return {$: 'SpacingStyle', a: a, b: b, c: c}; + }); +var $mdgriffith$elm_ui$Internal$Flag$spacing = $mdgriffith$elm_ui$Internal$Flag$flag(3); +var $mdgriffith$elm_ui$Internal$Model$spacingName = F2( + function (x, y) { + return 'spacing-' + ($elm$core$String$fromInt(x) + ('-' + $elm$core$String$fromInt(y))); + }); +var $mdgriffith$elm_ui$Element$spacing = function (x) { + return A2( + $mdgriffith$elm_ui$Internal$Model$StyleClass, + $mdgriffith$elm_ui$Internal$Flag$spacing, + A3( + $mdgriffith$elm_ui$Internal$Model$SpacingStyle, + A2($mdgriffith$elm_ui$Internal$Model$spacingName, x, x), + x, + x)); +}; +var $mdgriffith$elm_ui$Internal$Model$BorderWidth = F5( + function (a, b, c, d, e) { + return {$: 'BorderWidth', a: a, b: b, c: c, d: d, e: e}; + }); +var $mdgriffith$elm_ui$Element$Border$width = function (v) { + return A2( + $mdgriffith$elm_ui$Internal$Model$StyleClass, + $mdgriffith$elm_ui$Internal$Flag$borderWidth, + A5( + $mdgriffith$elm_ui$Internal$Model$BorderWidth, + 'b-' + $elm$core$String$fromInt(v), + v, + v, + v, + v)); +}; +var $mdgriffith$elm_ui$Element$Border$widthXY = F2( + function (x, y) { + return A2( + $mdgriffith$elm_ui$Internal$Model$StyleClass, + $mdgriffith$elm_ui$Internal$Flag$borderWidth, + A5( + $mdgriffith$elm_ui$Internal$Model$BorderWidth, + 'b-' + ($elm$core$String$fromInt(x) + ('-' + $elm$core$String$fromInt(y))), + y, + x, + y, + x)); + }); +var $mdgriffith$elm_ui$Element$Border$widthEach = function (_v0) { + var right = _v0.right; + var left = _v0.left; + var top = _v0.top; + var bottom = _v0.bottom; + return (_Utils_eq(top, bottom) && _Utils_eq(left, right)) ? (_Utils_eq(top, right) ? $mdgriffith$elm_ui$Element$Border$width(top) : A2($mdgriffith$elm_ui$Element$Border$widthXY, left, top)) : A2( + $mdgriffith$elm_ui$Internal$Model$StyleClass, + $mdgriffith$elm_ui$Internal$Flag$borderWidth, + A5( + $mdgriffith$elm_ui$Internal$Model$BorderWidth, + 'b-' + ($elm$core$String$fromInt(top) + ('-' + ($elm$core$String$fromInt(right) + ('-' + ($elm$core$String$fromInt(bottom) + ('-' + $elm$core$String$fromInt(left))))))), + top, + right, + bottom, + left)); +}; +var $author$project$Lessonpage$navbar = A2( + $mdgriffith$elm_ui$Element$row, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill), + $mdgriffith$elm_ui$Element$padding(20), + $mdgriffith$elm_ui$Element$spacing(20), + $mdgriffith$elm_ui$Element$Border$widthEach( + {bottom: 2, left: 0, right: 0, top: 0}) + ]), + _List_fromArray( + [ + A2( + $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$width( + $mdgriffith$elm_ui$Element$px(80)), + $mdgriffith$elm_ui$Element$height( + $mdgriffith$elm_ui$Element$px(40)) + ]), + $mdgriffith$elm_ui$Element$text('hi')), + A2( + $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [$mdgriffith$elm_ui$Element$alignRight]), + $mdgriffith$elm_ui$Element$text('Settings')) + ])); +var $author$project$Lessonpage$page = F2( + function (lesson, cid) { + var _v0 = A2($elm$core$Debug$log, 'lesson', lesson); + return A2( + $mdgriffith$elm_ui$Element$layout, + _List_fromArray( + [ + $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill), + $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$fill), + $mdgriffith$elm_ui$Element$inFront($author$project$Lessonpage$navbar) + ]), + A2( + $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [$mdgriffith$elm_ui$Element$centerX]), + A2($author$project$Lessonpage$lessonView, lesson, cid))); + }); +var $author$project$Router$lessonLoader = F3( + function (lid, cid, model) { + var _v0 = A2($elm$core$Dict$get, lid, model.lessons); + if (_v0.$ === 'Just') { + var lesson = _v0.a; + return _Utils_Tuple3( + model, + $elm$core$Platform$Cmd$none, + A2($author$project$Lessonpage$page, lesson, cid)); + } else { + return _Utils_Tuple3( + _Utils_update( + model, + {isLoading: true}), + $author$project$Api$fetchLesson(lid), + $author$project$Router$loadingPage); + } + }); +var $author$project$Router$notFound = A2( + $mdgriffith$elm_ui$Element$layout, + _List_Nil, + A2( + $mdgriffith$elm_ui$Element$el, + _List_fromArray( + [$mdgriffith$elm_ui$Element$centerX]), + $mdgriffith$elm_ui$Element$text('404'))); var $elm$html$Html$Attributes$href = function (url) { return A2( $elm$html$Html$Attributes$stringProperty, @@ -12307,67 +12830,6 @@ var $mdgriffith$elm_ui$Element$link = F2( _List_fromArray( [label]))); }); -var $author$project$Lessonpage$lessonView = function (lesson) { - return A2( - $mdgriffith$elm_ui$Element$link, - _List_Nil, - { - label: A2( - $mdgriffith$elm_ui$Element$el, - _List_Nil, - A2( - $mdgriffith$elm_ui$Element$column, - _List_Nil, - _List_fromArray( - [ - $mdgriffith$elm_ui$Element$text( - 'Lesson: ' + $elm$core$String$fromInt(lesson.id)), - $mdgriffith$elm_ui$Element$text(lesson.text) - ]))), - url: '/lesson' + $elm$core$String$fromInt(lesson.id) - }); -}; -var $author$project$Lessonpage$page = function (lesson) { - var _v0 = A2($elm$core$Debug$log, 'lesson', lesson); - return A2( - $mdgriffith$elm_ui$Element$layout, - _List_fromArray( - [ - $mdgriffith$elm_ui$Element$width($mdgriffith$elm_ui$Element$fill), - $mdgriffith$elm_ui$Element$height($mdgriffith$elm_ui$Element$fill) - ]), - A2( - $mdgriffith$elm_ui$Element$el, - _List_fromArray( - [$mdgriffith$elm_ui$Element$centerX]), - $author$project$Lessonpage$lessonView(lesson))); -}; -var $author$project$Router$lessonLoader = F2( - function (num, model) { - var _v0 = A2($elm$core$Dict$get, num, model.lessons); - if (_v0.$ === 'Just') { - var lesson = _v0.a; - return _Utils_Tuple3( - model, - $elm$core$Platform$Cmd$none, - $author$project$Lessonpage$page(lesson)); - } else { - return _Utils_Tuple3( - _Utils_update( - model, - {isLoading: true}), - $author$project$Api$fetchLesson(num), - $author$project$Router$loadingPage); - } - }); -var $author$project$Router$notFound = A2( - $mdgriffith$elm_ui$Element$layout, - _List_Nil, - A2( - $mdgriffith$elm_ui$Element$el, - _List_fromArray( - [$mdgriffith$elm_ui$Element$centerX]), - $mdgriffith$elm_ui$Element$text('404'))); var $author$project$Homepage$lessonPreview = function (lesson) { return A2( $mdgriffith$elm_ui$Element$link, @@ -12424,279 +12886,18 @@ var $author$project$Homepage$page = function (model) { [$mdgriffith$elm_ui$Element$centerX]), $author$project$Homepage$lessonsView(model.lessons))); }; -var $elm$url$Url$Parser$State = F5( - function (visited, unvisited, params, frag, value) { - return {frag: frag, params: params, unvisited: unvisited, value: value, visited: visited}; - }); -var $elm$url$Url$Parser$getFirstMatch = function (states) { - getFirstMatch: - while (true) { - if (!states.b) { - return $elm$core$Maybe$Nothing; - } else { - var state = states.a; - var rest = states.b; - var _v1 = state.unvisited; - if (!_v1.b) { - return $elm$core$Maybe$Just(state.value); - } else { - if ((_v1.a === '') && (!_v1.b.b)) { - return $elm$core$Maybe$Just(state.value); - } else { - var $temp$states = rest; - states = $temp$states; - continue getFirstMatch; - } - } - } - } -}; -var $elm$url$Url$Parser$removeFinalEmpty = function (segments) { - if (!segments.b) { - return _List_Nil; - } else { - if ((segments.a === '') && (!segments.b.b)) { - return _List_Nil; - } else { - var segment = segments.a; - var rest = segments.b; - return A2( - $elm$core$List$cons, - segment, - $elm$url$Url$Parser$removeFinalEmpty(rest)); - } - } -}; -var $elm$url$Url$Parser$preparePath = function (path) { - var _v0 = A2($elm$core$String$split, '/', path); - if (_v0.b && (_v0.a === '')) { - var segments = _v0.b; - return $elm$url$Url$Parser$removeFinalEmpty(segments); - } else { - var segments = _v0; - return $elm$url$Url$Parser$removeFinalEmpty(segments); - } -}; -var $elm$url$Url$Parser$addToParametersHelp = F2( - function (value, maybeList) { - if (maybeList.$ === 'Nothing') { - return $elm$core$Maybe$Just( - _List_fromArray( - [value])); - } else { - var list = maybeList.a; - return $elm$core$Maybe$Just( - A2($elm$core$List$cons, value, list)); - } - }); -var $elm$url$Url$percentDecode = _Url_percentDecode; -var $elm$url$Url$Parser$addParam = F2( - function (segment, dict) { - var _v0 = A2($elm$core$String$split, '=', segment); - if ((_v0.b && _v0.b.b) && (!_v0.b.b.b)) { - var rawKey = _v0.a; - var _v1 = _v0.b; - var rawValue = _v1.a; - var _v2 = $elm$url$Url$percentDecode(rawKey); - if (_v2.$ === 'Nothing') { - return dict; - } else { - var key = _v2.a; - var _v3 = $elm$url$Url$percentDecode(rawValue); - if (_v3.$ === 'Nothing') { - return dict; - } else { - var value = _v3.a; - return A3( - $elm$core$Dict$update, - key, - $elm$url$Url$Parser$addToParametersHelp(value), - dict); - } - } - } else { - return dict; - } - }); -var $elm$url$Url$Parser$prepareQuery = function (maybeQuery) { - if (maybeQuery.$ === 'Nothing') { - return $elm$core$Dict$empty; - } else { - var qry = maybeQuery.a; - return A3( - $elm$core$List$foldr, - $elm$url$Url$Parser$addParam, - $elm$core$Dict$empty, - A2($elm$core$String$split, '&', qry)); - } -}; -var $elm$url$Url$Parser$parse = F2( - function (_v0, url) { - var parser = _v0.a; - return $elm$url$Url$Parser$getFirstMatch( - parser( - A5( - $elm$url$Url$Parser$State, - _List_Nil, - $elm$url$Url$Parser$preparePath(url.path), - $elm$url$Url$Parser$prepareQuery(url.query), - url.fragment, - $elm$core$Basics$identity))); - }); -var $author$project$Router$Lesson = function (a) { - return {$: 'Lesson', a: a}; -}; -var $author$project$Router$Root = {$: 'Root'}; -var $elm$url$Url$Parser$Parser = function (a) { - return {$: 'Parser', a: a}; -}; -var $elm$url$Url$Parser$custom = F2( - function (tipe, stringToSomething) { - return $elm$url$Url$Parser$Parser( - function (_v0) { - var value = _v0.value; - var frag = _v0.frag; - var params = _v0.params; - var unvisited = _v0.unvisited; - var visited = _v0.visited; - if (!unvisited.b) { - return _List_Nil; - } else { - var next = unvisited.a; - var rest = unvisited.b; - var _v2 = stringToSomething(next); - if (_v2.$ === 'Just') { - var nextValue = _v2.a; - return _List_fromArray( - [ - A5( - $elm$url$Url$Parser$State, - A2($elm$core$List$cons, next, visited), - rest, - params, - frag, - value(nextValue)) - ]); - } else { - return _List_Nil; - } - } - }); - }); -var $elm$url$Url$Parser$int = A2($elm$url$Url$Parser$custom, 'NUMBER', $elm$core$String$toInt); -var $elm$url$Url$Parser$mapState = F2( - function (func, _v0) { - var value = _v0.value; - var frag = _v0.frag; - var params = _v0.params; - var unvisited = _v0.unvisited; - var visited = _v0.visited; - return A5( - $elm$url$Url$Parser$State, - visited, - unvisited, - params, - frag, - func(value)); - }); -var $elm$url$Url$Parser$map = F2( - function (subValue, _v0) { - var parseArg = _v0.a; - return $elm$url$Url$Parser$Parser( - function (_v1) { - var value = _v1.value; - var frag = _v1.frag; - var params = _v1.params; - var unvisited = _v1.unvisited; - var visited = _v1.visited; - return A2( - $elm$core$List$map, - $elm$url$Url$Parser$mapState(value), - parseArg( - A5($elm$url$Url$Parser$State, visited, unvisited, params, frag, subValue))); - }); - }); -var $elm$url$Url$Parser$oneOf = function (parsers) { - return $elm$url$Url$Parser$Parser( - function (state) { - return A2( - $elm$core$List$concatMap, - function (_v0) { - var parser = _v0.a; - return parser(state); - }, - parsers); - }); -}; -var $elm$url$Url$Parser$s = function (str) { - return $elm$url$Url$Parser$Parser( - function (_v0) { - var value = _v0.value; - var frag = _v0.frag; - var params = _v0.params; - var unvisited = _v0.unvisited; - var visited = _v0.visited; - if (!unvisited.b) { - return _List_Nil; - } else { - var next = unvisited.a; - var rest = unvisited.b; - return _Utils_eq(next, str) ? _List_fromArray( - [ - A5( - $elm$url$Url$Parser$State, - A2($elm$core$List$cons, next, visited), - rest, - params, - frag, - value) - ]) : _List_Nil; - } - }); -}; -var $elm$url$Url$Parser$slash = F2( - function (_v0, _v1) { - var parseBefore = _v0.a; - var parseAfter = _v1.a; - return $elm$url$Url$Parser$Parser( - function (state) { - return A2( - $elm$core$List$concatMap, - parseAfter, - parseBefore(state)); - }); - }); -var $elm$url$Url$Parser$top = $elm$url$Url$Parser$Parser( - function (state) { - return _List_fromArray( - [state]); - }); -var $author$project$Router$routeParser = $elm$url$Url$Parser$oneOf( - _List_fromArray( - [ - A2($elm$url$Url$Parser$map, $author$project$Router$Root, $elm$url$Url$Parser$top), - A2( - $elm$url$Url$Parser$map, - $author$project$Router$Lesson, - A2( - $elm$url$Url$Parser$slash, - $elm$url$Url$Parser$s('lesson'), - $elm$url$Url$Parser$int)) - ])); var $author$project$Router$router = function (model) { - var route = A2( - $elm$core$Maybe$withDefault, - $author$project$Router$NotFound, - A2($elm$url$Url$Parser$parse, $author$project$Router$routeParser, model.url)); - switch (route.$) { + var _v0 = model.route; + switch (_v0.$) { case 'Root': return _Utils_Tuple3( model, $elm$core$Platform$Cmd$none, $author$project$Homepage$page(model)); - case 'Lesson': - var num = route.a; - return A2($author$project$Router$lessonLoader, num, model); + case 'LessonR': + var lid = _v0.a; + var cid = _v0.b; + return A3($author$project$Router$lessonLoader, lid, cid, model); default: return _Utils_Tuple3(model, $elm$core$Platform$Cmd$none, $author$project$Router$notFound); }