diff --git a/104ab42f11_md/media/image1.png b/104ab42f11_md/media/image1.png
new file mode 100644
index 0000000..1f3dae6
Binary files /dev/null and b/104ab42f11_md/media/image1.png differ
diff --git a/104ab42f11_md/media/image2.png b/104ab42f11_md/media/image2.png
new file mode 100644
index 0000000..0140704
Binary files /dev/null and b/104ab42f11_md/media/image2.png differ
diff --git a/degrees.py b/degrees.py
new file mode 100644
index 0000000..956cb4c
--- /dev/null
+++ b/degrees.py
@@ -0,0 +1,164 @@
+from lark import Lark, Transformer, v_args
+
+
+
+
+"""describe college courses, their number of units, any other courses that are prerequisites, as well as various degrees which
+consist of groups of courses that must be taken. The groups have rules associated with them, such as:
+- take all (the following courses)
+- take n (where n=3 or 5 or something)
+- take at least n units from the following list (so the taken course's unit value must add up to n or greater)
+- and so on."""
+
+
+
+
+grammar = """
+ start: program
+
+ program: course_declaration*
+
+ course_declaration: "course" CNAME INT "prerequisites" (CNAME ","?)* "degree" CNAME "{" degree_rule* "}"
+
+ degree_rule: "take" ("all" | "at" INT "from") ("the" "following") "courses" course_list
+
+ course_list: (CNAME ","?)*
+
+ %import common.CNAME
+ %import common.INT
+ %import common.WS
+ %ignore WS
+"""
+
+class Course:
+ def __init__(self, name, units, prerequisites, degree):
+ self.name = name
+ self.units = units
+ self.prerequisites = prerequisites
+ self.degree = degree
+
+class DegreeRule:
+ def __init__(self, verb, n, course_list):
+ self.verb = verb
+ self.n = n
+ self.course_list = course_list
+
+class Degree:
+ def __init__(self, name, degree_rules):
+ self.name = name
+ self.degree_rules = degree_rules
+
+class Rule:
+ pass
+
+class TakeAll(Rule):
+ def __init__(self, courses):
+ self.courses = courses
+
+class TakeN(Rule):
+ def __init__(self, courses, n):
+ self.courses = courses
+ self.n = n
+
+class TakeNUnits(Rule):
+ def __init__(self, courses, n):
+ self.courses = courses
+ self.n = n
+
+@v_args(inline=True)
+class DSLTransformer(Transformer):
+ def __init__(self):
+ self.courses = {}
+ self.degrees = {}
+
+ def course_declaration(self, name, units, prerequisites, degree):
+ return Course(name, int(units), prerequisites.children, degree)
+
+ def degree(self, name, required_courses):
+ self.degrees[name] = Degree(name, required_courses)
+
+ def take_all(self, courses):
+ return TakeAll(courses)
+
+ def take_n(self, courses, n):
+ return TakeN(courses, n)
+
+ def take_n_units(self, courses, n):
+ return TakeNUnits(courses, n)
+
+ def degree_rule(self, items):
+ verb = items[0]
+ n = None
+ course_list = items[-1]
+ if len(items) == 4:
+ n = int(items[2])
+ return DegreeRule(verb, n, course_list.children)
+
+ def course_list(self, items):
+ return items[:-1]
+
+ def program(self, items):
+ courses = [item for item in items if isinstance(item, Course)]
+ degrees = [item for item in items if isinstance(item, Degree)]
+ return courses, degrees
+
+
+dsl = DSLTransformer()
+dsl.course('CS101', 3)
+dsl.course('CS102', 3, prerequisites=['CS101'])
+dsl.course('MATH101', 3)
+dsl.degree('CS', [
+ dsl.take_all(['CS101', 'CS102']),
+ dsl.take_n_units(['CS101', 'CS102', 'MATH101'], 9),
+ dsl.take_n(['CS101', 'CS102', 'MATH101'], 2),
+])
+
+print(dsl.courses)
+print(dsl.degrees)
+
+
+
+
+
+parser = Lark(grammar)
+transformer = DSLTransformer()
+
+def parse_dsl(dsl):
+ tree = parser.parse(dsl)
+ return transformer.transform(tree)
+
+dsl = """
+course CS101 3 prerequisites none degree CS {
+ take all the following courses {
+ CS102, CS103
+ }
+ take at least 6 from {
+ MATH101, MATH102, MATH103
+ }
+}
+"""
+
+courses, degrees = parse_dsl(dsl)
+print(courses)
+print(degrees)
+
+
+
+
+
+def compute_degree_progress(student_courses, degree):
+ total_units_completed = 0
+ total_required_units = 0
+ for course in degree['required_courses']:
+ if course['id'] in student_courses:
+ total_units_completed += course['units']
+ if 'additional_rules' in course:
+ for rule in course['additional_rules']:
+ if rule['type'] == 'at_least_n_units_from_list':
+ units_from_list = sum([c['units'] for c in degree['courses'] if c['id'] in student_courses and c['id'] in rule['course_list']])
+ if units_from_list < rule['n']:
+ break
+ total_required_units += course['units']
+ progress_percent = total_units_completed / total_required_units * 100 if total_required_units > 0 else 0
+ return progress_percent
+
diff --git a/interactive.py b/interactive.py
index e74efd0..5e54a1b 100644
--- a/interactive.py
+++ b/interactive.py
@@ -16,6 +16,15 @@ from canvas_secrets import flask_secretkey
from content import my_site
+
+
+
+### SET THIS ENV VAR TO GET RELOADING
+# (win)
+# set FLASK_ENV=development
+# (linux)
+# export FLASK_ENV=development
+
import socket
this_host = socket.gethostname()
@@ -155,6 +164,15 @@ def flask_thread(q):
return image_crop(filename,x,y,w,h,newname)
+ @app.route('/md', methods=['GET', 'POST'])
+ def convert_markdown():
+ if request.method == 'POST':
+ markdown_input = request.form.get('markdown_input', '')
+ html_output = markdown.markdown(markdown_input)
+ return render_template('basic.html', title='md -> html', html_output=html_output)
+ return render_template('convert.html')
+
+
#
# SAVING STUFF
@@ -166,10 +184,13 @@ def flask_thread(q):
path = request.form['path']
txt = request.form['content']
- o3 = codecs.open(server.writing_path + path, 'r', 'utf-8')
- orig_text = o3.read()
- o3.close()
-
+ try:
+ o3 = codecs.open(server.writing_path + path, 'r', 'utf-8')
+ orig_text = o3.read()
+ o3.close()
+ except Exception as e:
+ orig_text = ''
+
bu_filename = server.writing_path + 'older_copies/' + path + '_' + now + '.md'
o2 = codecs.open( bu_filename, 'w', 'utf-8' )
o2.write(orig_text)
@@ -321,7 +342,7 @@ def flask_thread(q):
- socketio.run(app, host= '0.0.0.0')
+ socketio.run(app, host= '0.0.0.0') # , debug=True
diff --git a/server.py b/server.py
index 5aaaba7..318937f 100644
--- a/server.py
+++ b/server.py
@@ -1,5 +1,6 @@
import json, codecs, re, markdown, os, pypandoc, striprtf, sqlite3, random, urllib
import subprocess, html, time
+from markdownify import markdownify as md
from striprtf.striprtf import rtf_to_text
from flask import render_template, Response
from flask import send_from_directory
@@ -145,8 +146,9 @@ def screenoff():
br = "
"
nl = "\n"
-style = """
+style = """
+
"""
@@ -188,6 +190,7 @@ def homepage():
a('Pi frame on','/displaypi/on') + br + br + \
a('Pi frame off','/displaypi/off') + br + br + \
a('Knowledge Base','/x/writing/index') + br + \
+ a('Markdown -> HTML converter','/md') + br + \
a('Gav web mirror','/mirror') + br + \
a('Graph of users','/x/user/1') + "
" + \
a('Courses in a dept','/x/dept/csis') + "
" + \
@@ -262,7 +265,12 @@ def writing(fname):
#output = pypandoc.convert_file('C:/Users/peter/Nextcloud/Documents/writing/' + fname, 'html',
output = pypandoc.convert_file(writing_path + fname, 'html',
extra_args=['--extract-media=%s' % hash ]) # file:///c:/Users/peter/Nextcloud/Documents/writing
- return style + output
+ output2 = pypandoc.convert_file(writing_path + fname, 'markdown',
+ extra_args=['--extract-media=%s' % hash+'_md' ]) # file:///c:/Users/peter/Nextcloud/Documents/writing
+ new_fname = fname[:-5] + '.md'
+ #as_md = md(output)
+ return style + output + in_form(editor(output2),new_fname)
+
return style + markdown.markdown( "".join( [ orgline(x) for x in inp.readlines() ] ) )
diff --git a/templates/basic.html b/templates/basic.html
new file mode 100644
index 0000000..403333f
--- /dev/null
+++ b/templates/basic.html
@@ -0,0 +1,14 @@
+
+
+