Package: chcko
chckoEducational problem server athttps://chcko.eudeveloped athttps://github.com/chcko/chckowith example content packagehttps://github.com/chcko/chcko-rch[e]cko.e[d]uwants to collect science problems,
usable by students with or without learn coaches around the world,
as an infrastructure.The content packages are python packages.GoalsCollect problemsMake the problems readily usable, also over the distanceMake it less effortto check one’s own understandingto check the progress of studentsto compose a school or home workto correct (as the server takes care of that)Help Bootstrap the Communitychckocan be installed locally, too.
Buthttps://chcko.euallows you to do without own hardware and server maintenanceCurrentlyhttps://chcko.euis only ongcloudfree quota,
which is regularly used up.Runninghttps://chcko.eufor a broader community produces less overall cost, though,
than everyone having their own servers.If you can identify with the goals of this project,help bootstrap the community,first by a smalldonationto raise the server quotaand second by contributing your own problem packages (example:chcko-r)Not just teacher,
also students can make achcko-Xpackage out of problems they solve.
Since they solve the problems anyway,why not using Python?and why not sharing the problems?URLPages are requested with this URL format:../<lang>/<page>?<query>Pages are:org: add roles and choose a role colorcontents: specific content items or overview if noquerydone: done problemstodo: assigned problemssome additional helper pagesExample URLs:https://chcko.eu/en/org?School=S&Field=F&Teacher=T&Class=C&Role=Rhttps://chcko.eu/en/contents?r.a&r.buhttps://chcko.eu/en/contents?r.a&&r.buhttps://chcko.eu/en/done?*&*With&&instead of one&as separator in acontentsquery (course),
only one problem at a time is shown.&&&marks the current position.
For example,.../en/contents?r.bd&&r.ba&&&r.ahasr.aas current item in the course.The namesSchool, Field, Teacher, Class, Roleform namespace levels to describe a studentrole.
The namespaces are of organizational nature.
The namepace names are taken from usual organizational structures.
What string is used in each level is up to the user.See alsoqueries.Use CasesNo LoginWithout login a randomRoleis generated.
One can revisit theRolelater via the URL, for examplehttps://chcko.eu/en/done?School=7f277b84&Field=8084&Teacher=5ab4&Class=87b5&Role=459671edc836WithOrgone can choose names.
One can choose names via the URL, too.
For example:https://chcko.eu/en/org?School=noschool&Field=2020&Teacher=noteacher&Class=noclass&Role=meWithout login these names, random or not, are not protected.
Their ownership changes to a logged-in user when accessed,
either viaOrgor via URL.Step-by-step try in class without logging in:Agree on a common ID for School, Field, Teacher and Class and
a scheme for the Role, e.g.FirstnameL[astname].Teacher visits:https://chcko.eu/en/contents?School=noschool&Field=2020&Teacher=noteacher&Class=noclass&Role=——-The teacher is a student, too.
This is the default for a logged in user.Alternatively:openhttps://chcko.euGo toOrg(top left)Enter the IDs.Press [OK].Go toContents.Students visit a problem (herer.bu) via:https://chcko.eu/en/contents?School=noschool&Field=2020&Teacher=noteacher&Class=noclass&Role=GabiB&r.buhttps://chcko.eu/en/contents?School=noschool&Field=2020&Teacher=noteacher&Class=noclass&Role=LauraB&r.buhttps://chcko.eu/en/contents?School=noschool&Field=2020&Teacher=noteacher&Class=noclass&Role=LiliB&r.bu…Alternatively they can also do the steps throughOrgonhttps://chcko.euandvisit the problem afterwards viahttps://chcko.eu/en?r.bu.After the students have solved the problems,
the teacher enters the URL.../en/done?<classId>&*&*to see if everybody was successful.any problem (*)of any student (*)of the class<classID>. The actual class ID must be used.https://chcko.eu/en/done?noclass&*&*Students can query the results, too,
if the class namespace is not owned by a logged in user.Reserve a NameLogin in.ThenGo toOrgand choose a name.Alternatively, after having logged in, visit an URL with the names of you choice, e.g.:https://chcko.eu/en/org?School=noschool&Field=2020&Teacher=noteacherCreate a ClassIn theOrgtab,
theRoleinput box uses the first of;,as a separator
to create a whole class with no owner (independent of logged in or not).Then send a link to each student (e.g. via email):https://chcko.eu/en/todo?School=noschool&Field=2020&Teacher=noteacher&Class=noclass&Role=StudentNameOr send the same link to all students and let them add theirStudentName.If the students log in, before visiting the URL, they take ownership of the role.AssignTo assign to others, you need to be logged in.In thecontentstab choose the problems
or use an URL:https://chcko.eu/en/contents?r.a&r.ckAt the end of the page you can choose classes or students to assign to.
Assigning a course (with the&&instead of&),
assigns the problems individually.URLs without problems cannot be assigned.The studentslog ingo to theTodotabsolve the assigned problemsFind problemsThere is no full text search engine yet.
To find a problem, there are these alternatives:Use the index pagehttps://chcko.eu/en/contentsClone content packages and use local text search (grep, …)Create PrintoutIf you addbareto the query string of the problem URL,
header and footer is dropped.
There is a printer symbol at the bottom right, which does that.
Then you cansave and open the file with a MS Word or Libre Officeprint from within your browser (possibly to a pdf file)use the command line withchromeorchromiumto create a PDFchrome --enable-logging --headless --disable-gpu --print-to-pdf=/full/path/to.pdf http://chcko.eu/en/contents?r.bk&r.c&r.i&cheader=Homework&bareCheck DoneYou can check the done problems below a namespace level like classif you own the level and you are logged inif the level is not ownedChange to the teacher / class / Role.Go to thedonetab.Add?*&*to the URL:https://chcko.eu/en/done?*&*Clicking on the names for class, teacher, … forwards to these URLs.*can be replaced by%2Awhen sending the link, because some programs drop the*.https://chcko.eu/en/done?%2A&%2A?<school>&<field>&<teacher>&<class>&<role>&<problem>isdefaulted to the leftwith the current role namesif omitted.*&*means: don’t take the default, but showanyroleandproblem.See alsodone.Remove an AssignmentThetodopage has the same query format as thedonepage.https://chcko.eu/en/todo?*&*Shows the given (and not yet done) assignments and
allows to delete them selectively.Assume RoleAs a logged in user you can have more roles.
These roles are listed by clicking in the role field
around the ☰.
Click on an entry to assume another role.Remove a RoleAssume the roleGo to theOrgtabChoosedeleteConfirmThere should be no easier way,
because you lose all the history of the role,
by deleting it.Change a RoleSame asRemove a Role,
but choosechangeinstead.This moves all the history associated with a role
to the new role and deletes the previous one.changeis a way toleave aclass(teacher,field,school) andjoin another classwithout loosing one’s history.Content PackagesIn a content packagecontent items<package_id>.<content_id>of the URL querycorrespond to the folderchcko-<package_id>/chcko/<package_id>/<content_id>/Example content package layout:chcko-r
  ├── chcko
  │   ├── conf.py
  │   ├── _images
  │   │   ├── r_dg_c1.png
  │   │   ├── ...
  │   └── r
  │       ├── initdb.py
  │       ├── __init__.py
  │       ├── a
  │       │   ├── de.html
  │       │   ├── en.html
  │       │   └── __init__.py
  │       ├── b
  │       │   ├── _de.html
  │       │   ├── de.rst
  │       │   ├── _en.html
  │       │   ├── en.rst
  │       │   ├── __init__.py
  │       │   └── vector_dot_cross.tex
  │       └── ...
  ├── ...
  ├── README.rst
  └── setup.pyImage file names in_imagesare either random or
otherwise unique by encoding package ID, problem ID, content and possibly language.__init__.pyis always there.
Altogether it is aPythonpackage,
withchckonamespaceGenerated files start with_(_<language_id>.html).<language_id>.rstcan containtikzimages.<language_id>.rstfiles are statically converted to_<language_id>.htmlwith:doit -kd. htmlinitdb.pyfills the database with content items. It is generated using:doit -kd. initdbOften it is better to just stick to HTML, though.
HTML files are actuallystpltemplate snippets,
for exampler/a/en.html:%path = "maths/trigonometry/sss"
%kind = 0 #problems (``chindnum`` converts from current's language kind names, see languages.py)
%level = 11 # school year starting from elementary
The sides of a triangle are
a={{ chiven.a }},
b={{ chiven.b }},
c={{ chiven.c }}.
How big are the angles (in degrees).
%champles=['e.g.'+e for e in ['23.3','100','56.7']]
%chq()Every content item must have the first 3 lines
starting with%path,%kindand%level.
They are used bydoit-kd.initdbto create the index.The global defines for problem templates
are made distinguishable from english words
by replacing the first consonant withch.chivenis whatchiven()in__init__.pyreturns.chq(defined inchelper.html) creates the input field or shows the result,
according the output ofchalc()(normally a list of numbers),
if noidxis specified.chquseschesults: calcuated result (fromchalc())chanswers: answer given by userchanswered: None or datetime, when answeredchoints: points for the answerchoks: answers that are OK (entries convertible to bool)chqoptionally uses (if defined):chames: as input names (per idx a html/tex string, e.g. r”(alpha)”)champles: input examples ( “ )chadios: texts forradio buttons(a tuple per idx).chalc()returns index number.checkos: texts forcheck boxes(a tuble per idx).chalc()returns list of indices as string of capital letters e.g.AC(chr(65+i)).chow: function that shows the result, e.g.util.txIfchq()is called for oneidxonly, the wrapping in a list can be dropped.Here is the__init__.pyof the example:importrandomimportmathasmfromchcko.chcko.hlpimportStructdefangle_deg(i,g):d=dict(zip('abc',([chiven.a,chiven.b,chiven.c]*2)[i:]))returneval('180*acos((a*a+b*b-c*c)/2/a/b)/pi',{**d,'acos':m.acos,'pi':m.pi})defchiven():random.seed()a,b=random.sample(range(1,10),2)c=random.randrange(max(a-b+1,b-a+1),a+b)returnStruct(a=a,b=b,c=c)defchalc(g):return[angle_deg(i,g)foriinrange(3)]names=[r'\(\alpha=\)',r'\(\beta=\)',r'\(\gamma=\)']__init__.pyprovides:chiven(): returnsStructof given, randomly generated numberschalc(): returns a list of wanted results as strings
(number string forchadios, strings ofA-Zfor OKcheckos)chorm(): optional functionchorm()to normalize the answer to make it comparable to the resultchequal(): optional function to compare each index ofchanswersandchesultsAll other special defines of a problem in__init__.pyare also made available to the template.The entries in the dict (Struct) returned fromchiven()can be overridden via the URL parameters.cheaderURL parameter is text placed at the beginning of a page with problems.A problem can also define its own javascript. As an example:r.idoes%include('r/i/coord'), which has a js script per problem numberchumber(see the result:r.i).%defscript():<scripttype="text/javascript"src="/static/graph.js"></script>%end%chripts['graph.js']=script%defscript():<scripttype="text/javascript">%fori,finenumerate(chiven.funcs):functionfun{{chumber}}{{i}}(x){{{f[1]}};}%endfunctiondrawall{{chumber}}(){varcs=createCS("{{chumber}}","cs_div{{chumber}}");cs.context.font="20px sans-serif";%fori,finenumerate(chiven.funcs):lastpos=cs.show(fun{{chumber}}{{i}},{{i}},2);cs.context.strokeText("{{str(i+1)}}",lastpos[0],lastpos[1]);%end}document.addEventListener("DOMContentLoaded",function(){drawall{{chumber}}();})</script>%end%chripts['funcs'+str(chumber)]=scriptNon-problem texts are OK, too, but should becontext-free,
as they are combined with other texts/problems to a page via an URL query string.Create a Content PackageLook at the example content package for guidancehttps://github.com/chcko/chcko-rTo add a new content package onhttps://chcko.eu:Name itchcko-<package_id>such thatit does not exist yet on pypi(.e.g.ris already taken)Test it locallyUpload it topypiadd it torequirements_ndb.txtwith a pull requesthttps://chcko.euwill be updated timely.You can also run a server locally with:runchckoIfchckois not installed:./runchcko_with_sql.py -s wsgiref
#prepend ``python3`` if your default python is python2Not installed content packages must be parallel to the mainchckofolder.With installedchcko:pip install --user chcko
#use pip3 if your default python is python2Create a new content package with:runchcko --init chcko-<id>You run this command also to fill
a repo you started on github and cloned local.Add a new content item with:doit -kd. newor:doit -kd. newrstEdit the problem text inen.htmlusing atext editor.
See the exampleabove.Then, from the root of the content package:doit -kd. html
doit -kd. initdbor:make htmlTo test, run the server with:runchcko [-s wsgiref]PlatformsIf you are familiar with Linux, use it, possibly on a virtual machine
likevirtualbox.
But all the needed tools are also available for Windows and MacOS.You will needgitpython >= 3.7On MacOS the developer command line tools are offered for install,
when you typegitin the terminal.Python3will also be available, then.To install the python packages for development,
in a terminal in a folder of your choice:git clone https://github.com/chcko/chcko
cd chcko
pip install --user -r requirements_dev.txt
#use pip3 if your default python is python2 (e.g. MacOS)
cd ..
git clone https://github.com/chcko/chcko-rSphinxis only needed if you useRST.Latexis needed, if you use Sphinx plugins
(sphinxcontrib.tikz,sphinxcontrib.texfigure).Content packages can have their own python dependencies.
Installing them, makes sure these are there.
Otherwise an install is not needed,
if the content packages are parallel tochcko.To run the server without installing:cd chcko
./runchcko_with_sql.py -s wsgiref
#prepend ``python3`` if your default python is python2To install:pip install --user chcko
pip install --user chcko-r
#use pip3 if your default python is python2To run the server with installed packages:runchckoDevelopmentThere are some other defines for the templates:chelf: the class for the page (see folders in mainchckopackages)chutil: instance ofUtildefined inchcko/util.pychlangs: list of all languages figuring in any of the content packageschdb: database class defined inchcko/sql.pyorchcko/ndb.pywith mixin fromchcko/hlp.pychuery: the current query stringchlang: current language (<domain>/<chlang>[/<page>]?<query>)chindnum(),chumkind(): convert between kind number and string for current language
(e.g."Problem"<->0, seelanguage.py)Now some historical development background.PurposeChcko is yet another solution for computer aided instructions (CAI).
The internet has a huge potential in teaching and learning.The main purpose:Automatically correct problemsInfrastructure to organize teaching (school, field, teacher, class, role/student)allow teachers/coaches to quickly check the problems of studentsThe use is of course not confined to schools.
Teachers, professors, tutors, coaches, students, autodidacts, …
can add problems and check themselves or others.Share content via separate content packages, likechcko-r.The numbers in problems are randomly generated.
This way a problem can be reused.
Students sitting next to each others in class will have different numbers and
therefore cannot copy the results.Chckocan be used remotely as well as in class.In class students can use the browser on their smartphones to answer problems.
Teachers can immediately see, who answered correctly or who has not yet answered.
This way the teacher is faster to find
those students who have not yet memorized something
or have not yet understood a concept or a relationship.Students can do problems immediately after the teacher’s explanation in class in the same lesson.
This way the studentsneed to pay attention,
because they will have to know immediately afterwardscannot copy from others, because the numbers are different,
even with problems only due in the next lessondo not need to admit that they have not understood,
because the teacher sees, if they are unable to do the problem.
Some students are too shy to ask.
There are other reasons,
why student’s incomprehension can stay unnoticed for too long.The teacher cannot look at all the done problems of a class at the same time,
but the software can.
To do it sequentially in class would hold up the students.
If the teacher takes the exercise books home,
there is an unwanted delay in feedback for the students.More parallelism in class is very important
in order to make the time spent there worthwhile for the students.The time spent by a teacher to correct exercise books is also
better invested in a good preparation:how to motivate the studentshow to present the topic as easy as possiblewhich questions to ask to practice and to verify that the students have understoodPlanEvery content has a unique ID = ID_author.ID_content.
This way no ID coordination is necessary once the author has an ID.
ID_author is the same as package_id inchcko-<package_id>.Every ID is also a folderID_authorID_content1ID_content2…IDs shall be as short as possible. They are best numbered through using a-znumbers would not make it a Python identifiercapital letters would collide with windows case insensitivity for file namesEvery content folder contains Python code and language filesA Python part (__init__.py) to randomly generate for problems.
It is also needed for content without numbers: just keep it empty.Language template files (en.html,de.html,it.html,fr.html,…)
that will produce html.en.htmlshould always be there as starting points for translations.A static off-line step is possible.
This allows to create content from other formats,
currently from restructured text files (.rst) using Sphinx.
This allows to use Sphinx contributions like tikz and texfigure (tex,tikz,chemfig, …) to create graphics.Human language context paths to problems are language dependent
and are therefore in the language files.More problems can be combined in one URL / http request (contentsquery)
e.g. to make a larger assignment.Problem/Content pages can reference other content or inline it
via the template engine (%include(`r.cy`)for html or or:inl:`r.cy`for RST).Answers to problems are stored in a DB and
combined with the language texts during loading.A role is identified by an ID path/hierarchy:school 1-n field 1-n teacher 1-n class 1-n roleVia this hierarchy a teacher has fast access to the done problems
of his classes and students via an URL query.Teachers can assign problems to their classes/students, which they access via atodoqueryTeachers see what their classes/students have done so far (donequery)Users initially get a generated role (generated random strings for each),
which they can change, though (orgquery).
There users can choose a color to help then see in which role they are.Registered users can have more roles.
Registration can also be done via Google, Twitter, Facebook or LinkedIn.DesignThe code tries to stay minimal:
Python 3 withbottleand a DB for the roles and problems.Database:The data model is:school 1-n field 1-n teacher 1-n class 1-n role 1-n problemThe first 5 are called a role.
A user has more roles.DB is there for answers to problems, not for the problem texts.OnGCP, the DB is DataStore usingndbOn other server the DB is a SQL database usingSqlAlchemyEnvironment VariablesCHCKOSECRET:a secret used to encode the user token cookieCHCKOPORT:used to change port for local serverSOCIAL_AUTH_<PROVIDER>_KEY:for social loginSOCIAL_AUTH_<PROVIDER>_SECRET:for social loginQueriesThe URL format is:URL = "https://"domain"/"lang"/"page"
domain = "chcko.eu"
lang = "en"|"de"|...
page = ["contents"]["?"{author"."problem["="count]"&"}]
       | "done"[rlinc]
       | "todo"
       | "org"
rlinc = [[[[[school&]field&]teacher&]class&]role&]("*"|query)
query = {field("~"|"="|"!"|"<"|">")value","}If<lang>is dropped, the last language or the browser setting is used.
Seelanguages.py.<page>is one ofcontents,done,todo,org.contentsis default, if dropped.<query>starts after the?.<query>is a&-separated list.<query>can containSchool=<...>&Field=<...>&Teacher=<...>&Class=<...>&Role=<...>for all pages.contentsWith../<lang>/contentsall current contents are listed. One can select more entries here.../en/contents?r.a&r.by=2(r.ais equivalent tor.a=1) would create
an English content page with oner.aand twor.byproblems.../en/?r.a&r.by=2is the same, i.e.contentsis the default page.Use&&instead of&to show one problem at a time (course).For logged-in users it is possible
to makeassignmentsto class/students with the same School-Field-Teacher prefix.
You must have created the teacher role, before the others.Problems have more questions and every question has points associated (default 1).
After checking the entered values at the top there will be a summary of achieved
points/total points twice, once not counting fields left empty.Thecontentsindex can be limited with:link: the author idlevel: corresponds to school year starting from elemntary (1, 2, …)kind: problems texts courses examples summaries formal fragments remarks
citations definitions theorems corollaries lemmas propositions axioms
conjectures claims identities paradoxes metapath: as given in the header of the content sourcesdone../<lang>/donelists the done problems with date and time and whether they were correct.
One can open every done problem or do it again.
It is possible to delete the selected problems.The query../<lang>/done?<school>&<field>&<teacher>&<class>&<role>&<problem>allowsa student to filter his problemsa teacher to see the problems of his classes or studentsOmitted entrieson the leftwill be filled by the corresponding current role IDs.
Therefore a student only needs<problem>, if it should be filtered at all.<..>are placeholders for the actual strings.For ‘no restriction’*is used.An entry has this format:name|field op value[,field op value[,...]]nameis the name of the recordfieldis a field of the recordAll records have a name,userkeyandchreated. School, Field,
Teacher and Class have no other fields.  In addition Role hascolorand Problem haschuery,chlang,chiven,chreated,chanswered,chinputids,chesults,choks,choints,chanswers,chumber.opconsists of~=!<>, where~means=.
For the age of a problem (sincechreated)
these abbreviations can be used:d=days, H=hours, M=minutes, S=seconds1DK&*&d>3,d<1would show all problems younger than 3 days (d) and
older than one day of students from class1DKsuggestionBookmark often used requests.Registered user’s data is protected against queries from anonymous users or other registered users.todo../<lang>/todolists the assignments with date/time given and date/time due.org../<lang>/orgallows to add, change or delete IDs for
School, Field, Teacher, Class and Role.
For fields left empty-is used for logged in usersa random ID is generated non-logged-in usersSetting role IDs fails, if the role is owned already.
Role prefixes of others are italic.
These other users can query your done problems.newwill create a new role.changewill change the identification of the current role,
i.e. all the problems done will be copied over.deletewill delete the role and all its done problems.Acolorcan be chosen to more easily see in which role one is.PermissionsOne level of privacy is via the IDs you choose.  How the IDs link to the
real things is only know to you.  You could use first or last letter of names,
add some additional characters, or do some other obfuscation, without
compromising an easy mapping to the real things or person for your purpose.All unregistered users fall into one user category. Therefore every other
unregistered user can query all other unregistered users’ problems (non-owned).A logged-in user assumes ownership of non-owned roles.If you register and create instances of school, field, teacher, class and student,
then they are associated to you as a user (owned).
Then you can query all instances below your instance in the hierarchy:School
    n Fields
        n Teachers
            n Classes
                n RolesE.g.If a teacher role belongs to you, then classes and students that use the same
IDs up to and inclusive teacher as your IDs, then you will be able to query them in thedonepage, even if they belong to some other user.A director in an educational institution could make a School ID. If all teachers
use the same School ID, then the director will be able to query the whole hierarchy.On the other hand, if you start your query above an instance that does not belong
to you, you will not see anything below, even if you have instances somewhere
in the deeper levels of the hierarchy.In.../<lang>/done?<school>&<field>&<teacher>&<class>&<role>&<problem>you can drop instances from the left, immediately after the?..../<lang>/done?aclass&*&d>2would query all problems of any student
of classaclassnot older than 2 days.
For this to workaclassneeds to belong to you.
If it does not, but the teacher role above belongs to your, then you can still query
by entering.../<lang>/done?ateacher&aclass&*&d>2.History2013As I was about to engage in a teaching job in the beginning of 2013 I was
looking for a way adequate for our timesto follow the progress of my studentsto automate certain activitiesI did not find a finished solution fitting to my ideas,
but I found Google AppEngine, which seemed to be a good basis for an own project.During my teaching job it was still in a very unsophisticated state,
but it was usable already. During that time I added mostly problems, some summaries
or other texts that did fit into the topics in class.The first name,mamchecker,
came about from this school’s abbreviation of the subject mathematics as MAM.Since summer 2013 I restructured the code and added user management
and I translated the problems and texts into English.As I did not continue teaching in autumn,
my major motivation for the additional effort was to make my initial effort
usable for others.2020I was kept busy 5+ years by a employment.
Now I revisited the project,renamed it tochckoupdated it to Python 3 andto the change at Google AppEngine (now part ofGCP):ndbchanges, no email any moreadded support for SQL databases usingsqlalchemymade it a python packagechckoseparated the content to a separatechcko-rpackage,
as an examplemade some fixes