{"id":18947183,"url":"https://github.com/qedsoftware/evolution","last_synced_at":"2025-09-02T10:37:25.330Z","repository":{"id":145932498,"uuid":"96542568","full_name":"qedsoftware/evolution","owner":"qedsoftware","description":"Why pay Kaggle when you can play for free?","archived":false,"fork":false,"pushed_at":"2017-09-01T08:31:54.000Z","size":332,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-25T13:48:37.186Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://evolution.qed.ai","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qedsoftware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-07-07T13:45:24.000Z","updated_at":"2018-01-13T08:15:55.000Z","dependencies_parsed_at":"2023-07-10T08:33:41.975Z","dependency_job_id":null,"html_url":"https://github.com/qedsoftware/evolution","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/qedsoftware/evolution","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qedsoftware%2Fevolution","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qedsoftware%2Fevolution/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qedsoftware%2Fevolution/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qedsoftware%2Fevolution/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qedsoftware","download_url":"https://codeload.github.com/qedsoftware/evolution/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qedsoftware%2Fevolution/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273272045,"owners_count":25075971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T13:09:10.916Z","updated_at":"2025-09-02T10:37:25.319Z","avatar_url":"https://github.com/qedsoftware.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Evolution\n\n## Goals\n\nSimple, robust system to streamline the work of data scientists, allowing them to easily verify their results in an objective, non-biased way.\n\n## Licensing\n\nCopyright (c) 2016 Quantitative Engineering Design (https://qed.ai). All rights reserved.\n\nThis software is distributed under the GNU Affero General Public License, v3.0, which is included in LICENSE.txt.\n\n\n## Status: Alpha\nThis piece of software went through some QA testing and seems stable.\n\n## Installation\n\nSee ``deploy.sh`` for executable example.\n\nPut local settings into ``local_settings.py`` in the main directory. You can base it on ``local_settings.py.example``. Without this file the system won't run.\n\nAdditionaly, you should install ``python-prctl``. This package is unavailable on OS X, though. You can add ``os.environ['prctl_disabled']=\"1\"`` to local_settings.py to disable the use of this package.\n\nCreate the first superuser by running ``./manage.py createsuperuser``.\n\n## Technologies\n\n* Python3\n* Django\n* Sass\n* PostgreSQL (may work with other dbs, but postgres is the only supported)\n* nginx (may work with other web servers)\n* Github-flavored Markdown (for writing descriptions, announcements etc.)\n\n## Contact\n\nFor developer issues, please start a ticket in Github. You can also write to the dev team directly at evolution-dev@qed.ai.\nFor other issues, please write to: evolution@qed.ai\n\n\n## For developers\n\nAll matters in this section are open to discussion.\n\n### Design philosophy\n\n#### Leading thoughts\n\nThis system should stay small and focused. If our needs grow big, then split the application to into several libraries/services/apps.\n\nCorrectness over convenience.\n\nIf in doubt, stick with simplicity.\n\nBe honest in your code. If something is wrong it should look wrong. If the code feels unclean or you need to workaround something, leave a comment, make it obvious. And no abstraction is usually better than bad abstraction.\n\nDRY is very important, but do not mistake coincidence for a rule. Separation of concerns is even more important.\n\nIf there is some part that does not belong to webapp, like a scoring runner, keep it separate. And do not force Django dependencies on it.\n\n#### Design conventions\n\nThin models and thin views. Put the logic into separate classes and functions - focused on one task and if possible not touching the db. By default put them in ``models.py``, but if there is some clear category, put them in separate file.\n\nModels themselves should be only used as data persistence object, don't put business logic into them. Models already have their responsibility - persistence objects. And it really helps with Separations of Concerns and Interface Segregation.\n\nNeither models nor business logic should know anything about the views. Be really strict about it.\n\nViews should only be an interface, the \"adapter\" from http to business logic. It should be easy to add a json or commandline interface. Views know about models, but keep coupling minimal. Coupling templates and views isn't a big problem, but avoid it if is not necessary.\n\n#### Architecture\n\nThe ``grading`` app handles grading. It does not know about the contests or the web interface. Queueing, set up, and running of the scoring mechanism belongs there. The running and isolating of the scoring script is done by an external mechanism (run_scoring.py). This external mechanism is likely to grow. We may want to factor the grading logic out of the web app in the future.\n\nThe scoring has the following layers:\n1. ``./manage.py grading`` - a simple loop polling for jobs\n2. ``./manage.py grading_attempt_safe`` - runs already created grading attempt, isolating possible failures, by running next layer in a separate process\n3. ``./manage.py grading_attempt`` - actually runs the grading attempt, gets the grading params from the db and sets up the grading environment.\n4. ``run_scoring.py`` - runs scoring scripts, trying to prevent it from using too much resources. It is not a proper isolation, just something to prevent stupid bugs from bringing down the whole system.\n\nThis system supports only a single contest type and this decision allows it to stay simple. It is handled by the ``contests`` app. It handles all the contest-specific matters. Contests shouldn't care about the specifics of the grading, all of that should be handled by ``grading``.\n\n### Code conventions\n\nPrefer class-based views. They allow for more declarative styles and very handy mix-in functionality.\n\nDon't depend too much on the admin interface. The usual administrative actions should be available from the normal interface. Admin should stay simple. Direct data access mechanism for superadmins only.\n\nEach time we use a comment, it is a failure to express ourselves naturally in code.\n\nTODOs in the code are generally welcome, with some restrictions:\n* The goal of TODO is to inform the developers that the solution is far from ideal and to encourage them to fix it, rather than workaround it.\n* Fixing the problem NOW is preferred to fixing it in the future. TODOs should be only used when just fixing it would be a major distraction or the developer is not sure how to approach it.\n* Use TODOs only for code related issues. Use TODO if a solution is not clean enough, insecure or doesn't work well enough. Missing features should be tickets not TODOs.\n* TODO should be reasonably concrete. No remarks such as \"refactor this project\". \"This class is bad because ...\" is OK. \"Do X\" is even better.\n* TODOs should be added with the possibility in mind, that they may stay for a long time unfixed. If it is something of priority add a ticket (and maybe TODO for navigation).\n* The developers must remember that TODO is only a suggestion. If they see a better way, they don't have to stick with TODO instructions.\n* If reading the code feels like swimming in TODO sea, it is a sign that something is seriously wrong - refactor it now.\n\n### Testing\n\nBoth white-box and black-box tests are welcome.\n\nWe want all views to have behavioral tests and it is primary way of testing.\nBut testing the business layer is also very useful - allows testing more reliably, more thoroughly and errors are much easier to debug.\n\nAvoid writing \"fragile\" tests - broken with every change, even if the code still works correctly. The most important point here is to avoid hardcoding full html chunks. Use beautiful soup if you have to. And if you can avoid looking too much at the html at all.\n\n#### Coverage\n\nWe use ``coverage`` (https://pypi.python.org/pypi/coverage).\n\nYou can simply run ``./coverage.sh`` and the results will be found in ``htmlcov/`` directory.\n\nFor more advanced usage see: https://coverage.readthedocs.org/en/coverage-4.0.3/\n\n### On UX goals\n\nUsable, simple, clean.\n\nHide the underlying complexity from the user. The contest system should give the user sense of simplicity and robustness.\n\nTry to keep pages simple and focused on one thing, with flat menus and hierarchies.\n\nMost users expect something less minimalistic styling-wise. We probably should make it look more fancy and more \"on purpose\". We want to avoid reaction \"oh, there's no css\", even though almost everything is styled.\n\nSupporting strange resolutions and mobile devices is nice, but is not going to be common, so we do not have to think a lot about that.\n\n### On technology choices\n\nBe conservative. It is painful to have unsupported and badly designed dependencies, so add them with care. In particular, avoid unpopular Django apps - these tend to go outdated quickly. If possible try to abstract away dependencies that are used in many places so that they can be painlessly replaced.\n\n\n#### Why not Celery?\n\nIn the Django world, Celery is a standard solution for running jobs in the background. So it is understandable that people may ask why we do not just poll the database. There are some good reasons:\n\n##### Simplicity\n\nA single daemon asks for submissions to judge.\nHaving 1-1 relation between the db and what the system is actually doing is very valuable. Monitoring is just trivial.\n\n##### Reliability\n\nWe keep perfect information about the grading state in the database. We never have to worry about losing jobs. Remember that we have many of them, and often they come in bulk, it may be hard to notice.\n\nTroubleshooting is very easy - we can always see what exactly the daemon is doing and what data is stored in the database. That is not so obvious with any queueing solution I know.\n\nRabbitMQ, which is the recommended message queue for Celery sometimes fails. And this is a nightmare. Do we have any connoisseurs of Erlang dumps?\n\n##### Features\n\nPolling approach allows to add priorities or more advanced ordering. This has some nice properties, such as:\n\n* If submissions are marked for grading twice before the grading actually starts, then it is graded only once. \n* If the grading daemon is disabled, then nothing bad happens, and once it comes back it just picks up any pending submission without a problem.\n* If there is a need to re-judge data directly from the database, it is easy.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqedsoftware%2Fevolution","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqedsoftware%2Fevolution","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqedsoftware%2Fevolution/lists"}