├── .gitignore ├── 404.html ├── CNAME ├── Gemfile ├── Gemfile.lock ├── IAP ├── .gitignore └── README.md ├── LICENSE ├── README.md ├── _config.yml ├── _includes ├── footer.html ├── head.html └── header.html ├── _layouts └── default.html ├── _sass ├── minima.scss └── minima │ ├── _base.scss │ ├── _layout.scss │ └── _syntax-highlighting.scss ├── accolade ├── README.md ├── ct-english.txt └── ct-review-sicp-js.png ├── assets ├── main.scss └── sourcepower.ico ├── deployment ├── README.md ├── auth │ └── README.md ├── auxilliary │ └── README.md ├── backend │ ├── README.md │ ├── aws-manual.md │ ├── shared.md │ └── terraform.md ├── frontend │ ├── README.md │ └── aws.md └── maint │ └── add-users.md ├── developer └── README.md ├── educator ├── README.md ├── assessment │ └── README.md ├── game │ └── README.md ├── github │ └── README.md └── voting │ └── README.md ├── learner ├── README.md ├── github │ └── README.md └── x │ └── README.md ├── package └── README.md ├── research └── README.md └── vanilla └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | .jekyll-cache 4 | .jekyll-metadata 5 | vendor 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /404.html 3 | layout: default 4 | --- 5 | 6 | 19 | 20 |
21 |

404

22 | 23 |

Page not found :(

24 |

The requested page could not be found.

25 |
26 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | about.sourceacademy.org -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | # Hello! This is where you manage which Jekyll version is used to run. 3 | # When you want to use a different version, change it below, save the 4 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 5 | # 6 | # bundle exec jekyll serve 7 | # 8 | # This will help ensure the proper Jekyll version is running. 9 | # Happy Jekylling! 10 | # gem "jekyll", "~> 4.2.0" 11 | # This is the default theme for new Jekyll sites. You may change this to anything you like. 12 | # gem "minima", "~> 2.5" 13 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 14 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 15 | gem "github-pages", "~> 231", group: :jekyll_plugins 16 | # If you have any plugins, put them here! 17 | group :jekyll_plugins do 18 | gem "jekyll-feed", "~> 0.12" 19 | end 20 | 21 | # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem 22 | # and associated library. 23 | platforms :mingw, :x64_mingw, :mswin, :jruby do 24 | gem "tzinfo", "~> 1.2" 25 | gem "tzinfo-data" 26 | end 27 | 28 | # Performance-booster for watching directories on Windows 29 | gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] 30 | 31 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (7.1.3.2) 5 | base64 6 | bigdecimal 7 | concurrent-ruby (~> 1.0, >= 1.0.2) 8 | connection_pool (>= 2.2.5) 9 | drb 10 | i18n (>= 1.6, < 2) 11 | minitest (>= 5.1) 12 | mutex_m 13 | tzinfo (~> 2.0) 14 | addressable (2.8.6) 15 | public_suffix (>= 2.0.2, < 6.0) 16 | base64 (0.2.0) 17 | bigdecimal (3.1.6) 18 | coffee-script (2.4.1) 19 | coffee-script-source 20 | execjs 21 | coffee-script-source (1.12.2) 22 | colorator (1.1.0) 23 | commonmarker (0.23.10) 24 | concurrent-ruby (1.2.3) 25 | connection_pool (2.4.1) 26 | dnsruby (1.71.0) 27 | simpleidn (~> 0.2.1) 28 | drb (2.2.1) 29 | em-websocket (0.5.3) 30 | eventmachine (>= 0.12.9) 31 | http_parser.rb (~> 0) 32 | ethon (0.16.0) 33 | ffi (>= 1.15.0) 34 | eventmachine (1.2.7) 35 | execjs (2.9.1) 36 | faraday (2.9.0) 37 | faraday-net_http (>= 2.0, < 3.2) 38 | faraday-net_http (3.1.0) 39 | net-http 40 | ffi (1.16.3) 41 | forwardable-extended (2.6.0) 42 | gemoji (4.1.0) 43 | github-pages (231) 44 | github-pages-health-check (= 1.18.2) 45 | jekyll (= 3.9.5) 46 | jekyll-avatar (= 0.8.0) 47 | jekyll-coffeescript (= 1.2.2) 48 | jekyll-commonmark-ghpages (= 0.4.0) 49 | jekyll-default-layout (= 0.1.5) 50 | jekyll-feed (= 0.17.0) 51 | jekyll-gist (= 1.5.0) 52 | jekyll-github-metadata (= 2.16.1) 53 | jekyll-include-cache (= 0.2.1) 54 | jekyll-mentions (= 1.6.0) 55 | jekyll-optional-front-matter (= 0.3.2) 56 | jekyll-paginate (= 1.1.0) 57 | jekyll-readme-index (= 0.3.0) 58 | jekyll-redirect-from (= 0.16.0) 59 | jekyll-relative-links (= 0.6.1) 60 | jekyll-remote-theme (= 0.4.3) 61 | jekyll-sass-converter (= 1.5.2) 62 | jekyll-seo-tag (= 2.8.0) 63 | jekyll-sitemap (= 1.4.0) 64 | jekyll-swiss (= 1.0.0) 65 | jekyll-theme-architect (= 0.2.0) 66 | jekyll-theme-cayman (= 0.2.0) 67 | jekyll-theme-dinky (= 0.2.0) 68 | jekyll-theme-hacker (= 0.2.0) 69 | jekyll-theme-leap-day (= 0.2.0) 70 | jekyll-theme-merlot (= 0.2.0) 71 | jekyll-theme-midnight (= 0.2.0) 72 | jekyll-theme-minimal (= 0.2.0) 73 | jekyll-theme-modernist (= 0.2.0) 74 | jekyll-theme-primer (= 0.6.0) 75 | jekyll-theme-slate (= 0.2.0) 76 | jekyll-theme-tactile (= 0.2.0) 77 | jekyll-theme-time-machine (= 0.2.0) 78 | jekyll-titles-from-headings (= 0.5.3) 79 | jemoji (= 0.13.0) 80 | kramdown (= 2.4.0) 81 | kramdown-parser-gfm (= 1.1.0) 82 | liquid (= 4.0.4) 83 | mercenary (~> 0.3) 84 | minima (= 2.5.1) 85 | nokogiri (>= 1.13.6, < 2.0) 86 | rouge (= 3.30.0) 87 | terminal-table (~> 1.4) 88 | github-pages-health-check (1.18.2) 89 | addressable (~> 2.3) 90 | dnsruby (~> 1.60) 91 | octokit (>= 4, < 8) 92 | public_suffix (>= 3.0, < 6.0) 93 | typhoeus (~> 1.3) 94 | html-pipeline (2.14.3) 95 | activesupport (>= 2) 96 | nokogiri (>= 1.4) 97 | http_parser.rb (0.8.0) 98 | i18n (1.14.4) 99 | concurrent-ruby (~> 1.0) 100 | jekyll (3.9.5) 101 | addressable (~> 2.4) 102 | colorator (~> 1.0) 103 | em-websocket (~> 0.5) 104 | i18n (>= 0.7, < 2) 105 | jekyll-sass-converter (~> 1.0) 106 | jekyll-watch (~> 2.0) 107 | kramdown (>= 1.17, < 3) 108 | liquid (~> 4.0) 109 | mercenary (~> 0.3.3) 110 | pathutil (~> 0.9) 111 | rouge (>= 1.7, < 4) 112 | safe_yaml (~> 1.0) 113 | jekyll-avatar (0.8.0) 114 | jekyll (>= 3.0, < 5.0) 115 | jekyll-coffeescript (1.2.2) 116 | coffee-script (~> 2.2) 117 | coffee-script-source (~> 1.12) 118 | jekyll-commonmark (1.4.0) 119 | commonmarker (~> 0.22) 120 | jekyll-commonmark-ghpages (0.4.0) 121 | commonmarker (~> 0.23.7) 122 | jekyll (~> 3.9.0) 123 | jekyll-commonmark (~> 1.4.0) 124 | rouge (>= 2.0, < 5.0) 125 | jekyll-default-layout (0.1.5) 126 | jekyll (>= 3.0, < 5.0) 127 | jekyll-feed (0.17.0) 128 | jekyll (>= 3.7, < 5.0) 129 | jekyll-gist (1.5.0) 130 | octokit (~> 4.2) 131 | jekyll-github-metadata (2.16.1) 132 | jekyll (>= 3.4, < 5.0) 133 | octokit (>= 4, < 7, != 4.4.0) 134 | jekyll-include-cache (0.2.1) 135 | jekyll (>= 3.7, < 5.0) 136 | jekyll-mentions (1.6.0) 137 | html-pipeline (~> 2.3) 138 | jekyll (>= 3.7, < 5.0) 139 | jekyll-optional-front-matter (0.3.2) 140 | jekyll (>= 3.0, < 5.0) 141 | jekyll-paginate (1.1.0) 142 | jekyll-readme-index (0.3.0) 143 | jekyll (>= 3.0, < 5.0) 144 | jekyll-redirect-from (0.16.0) 145 | jekyll (>= 3.3, < 5.0) 146 | jekyll-relative-links (0.6.1) 147 | jekyll (>= 3.3, < 5.0) 148 | jekyll-remote-theme (0.4.3) 149 | addressable (~> 2.0) 150 | jekyll (>= 3.5, < 5.0) 151 | jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) 152 | rubyzip (>= 1.3.0, < 3.0) 153 | jekyll-sass-converter (1.5.2) 154 | sass (~> 3.4) 155 | jekyll-seo-tag (2.8.0) 156 | jekyll (>= 3.8, < 5.0) 157 | jekyll-sitemap (1.4.0) 158 | jekyll (>= 3.7, < 5.0) 159 | jekyll-swiss (1.0.0) 160 | jekyll-theme-architect (0.2.0) 161 | jekyll (> 3.5, < 5.0) 162 | jekyll-seo-tag (~> 2.0) 163 | jekyll-theme-cayman (0.2.0) 164 | jekyll (> 3.5, < 5.0) 165 | jekyll-seo-tag (~> 2.0) 166 | jekyll-theme-dinky (0.2.0) 167 | jekyll (> 3.5, < 5.0) 168 | jekyll-seo-tag (~> 2.0) 169 | jekyll-theme-hacker (0.2.0) 170 | jekyll (> 3.5, < 5.0) 171 | jekyll-seo-tag (~> 2.0) 172 | jekyll-theme-leap-day (0.2.0) 173 | jekyll (> 3.5, < 5.0) 174 | jekyll-seo-tag (~> 2.0) 175 | jekyll-theme-merlot (0.2.0) 176 | jekyll (> 3.5, < 5.0) 177 | jekyll-seo-tag (~> 2.0) 178 | jekyll-theme-midnight (0.2.0) 179 | jekyll (> 3.5, < 5.0) 180 | jekyll-seo-tag (~> 2.0) 181 | jekyll-theme-minimal (0.2.0) 182 | jekyll (> 3.5, < 5.0) 183 | jekyll-seo-tag (~> 2.0) 184 | jekyll-theme-modernist (0.2.0) 185 | jekyll (> 3.5, < 5.0) 186 | jekyll-seo-tag (~> 2.0) 187 | jekyll-theme-primer (0.6.0) 188 | jekyll (> 3.5, < 5.0) 189 | jekyll-github-metadata (~> 2.9) 190 | jekyll-seo-tag (~> 2.0) 191 | jekyll-theme-slate (0.2.0) 192 | jekyll (> 3.5, < 5.0) 193 | jekyll-seo-tag (~> 2.0) 194 | jekyll-theme-tactile (0.2.0) 195 | jekyll (> 3.5, < 5.0) 196 | jekyll-seo-tag (~> 2.0) 197 | jekyll-theme-time-machine (0.2.0) 198 | jekyll (> 3.5, < 5.0) 199 | jekyll-seo-tag (~> 2.0) 200 | jekyll-titles-from-headings (0.5.3) 201 | jekyll (>= 3.3, < 5.0) 202 | jekyll-watch (2.2.1) 203 | listen (~> 3.0) 204 | jemoji (0.13.0) 205 | gemoji (>= 3, < 5) 206 | html-pipeline (~> 2.2) 207 | jekyll (>= 3.0, < 5.0) 208 | kramdown (2.4.0) 209 | rexml 210 | kramdown-parser-gfm (1.1.0) 211 | kramdown (~> 2.0) 212 | liquid (4.0.4) 213 | listen (3.9.0) 214 | rb-fsevent (~> 0.10, >= 0.10.3) 215 | rb-inotify (~> 0.9, >= 0.9.10) 216 | mercenary (0.3.6) 217 | minima (2.5.1) 218 | jekyll (>= 3.5, < 5.0) 219 | jekyll-feed (~> 0.9) 220 | jekyll-seo-tag (~> 2.1) 221 | minitest (5.22.2) 222 | mutex_m (0.2.0) 223 | net-http (0.4.1) 224 | uri 225 | nokogiri (1.18.8-arm64-darwin) 226 | racc (~> 1.4) 227 | nokogiri (1.18.8-x86_64-darwin) 228 | racc (~> 1.4) 229 | nokogiri (1.18.8-x86_64-linux-gnu) 230 | racc (~> 1.4) 231 | octokit (4.25.1) 232 | faraday (>= 1, < 3) 233 | sawyer (~> 0.9) 234 | pathutil (0.16.2) 235 | forwardable-extended (~> 2.6) 236 | public_suffix (5.0.4) 237 | racc (1.8.1) 238 | rb-fsevent (0.11.2) 239 | rb-inotify (0.10.1) 240 | ffi (~> 1.0) 241 | rexml (3.3.9) 242 | rouge (3.30.0) 243 | rubyzip (2.3.2) 244 | safe_yaml (1.0.5) 245 | sass (3.7.4) 246 | sass-listen (~> 4.0.0) 247 | sass-listen (4.0.0) 248 | rb-fsevent (~> 0.9, >= 0.9.4) 249 | rb-inotify (~> 0.9, >= 0.9.7) 250 | sawyer (0.9.2) 251 | addressable (>= 2.3.5) 252 | faraday (>= 0.17.3, < 3) 253 | simpleidn (0.2.1) 254 | unf (~> 0.1.4) 255 | terminal-table (1.8.0) 256 | unicode-display_width (~> 1.1, >= 1.1.1) 257 | typhoeus (1.4.1) 258 | ethon (>= 0.9.0) 259 | tzinfo (2.0.6) 260 | concurrent-ruby (~> 1.0) 261 | unf (0.1.4) 262 | unf_ext 263 | unf_ext (0.0.9.1) 264 | unicode-display_width (1.8.0) 265 | uri (0.13.2) 266 | 267 | PLATFORMS 268 | arm64-darwin-23 269 | x86_64-darwin-19 270 | x86_64-linux 271 | 272 | DEPENDENCIES 273 | github-pages (~> 231) 274 | jekyll-feed (~> 0.12) 275 | tzinfo (~> 1.2) 276 | tzinfo-data 277 | wdm (~> 0.1.1) 278 | 279 | BUNDLED WITH 280 | 2.2.10 281 | -------------------------------------------------------------------------------- /IAP/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /IAP/README.md: -------------------------------------------------------------------------------- 1 | # A Taste of Programming with SICP JS, IAP @ MIT, January 18-28, 2022 2 | 3 | ## Description 4 | 5 | We can understand some computer programs in the way we solve math equations: by performing one simple algebraic step after another, until we reach an answer. This Independent Activity introduces programming in this way, inspired by the first chapter of [Structure and Interpretation of Computer Programs, JavaScript edition](https://sourceacademy.org/sicpjs/) (SICP JS). We start from first principles, by looking at functions that you know from mathematics, but before long, you will program interesting graphics and sound patterns using the Source Academy, a website built for SICP JS. The Activity offers entertaining and thought-provoking insights into the essence of computation, and at the same time an introduction to programming using the popular programming language JavaScript. 6 | 7 | You can participate on one to six days, depending on your preference. Each day has a lecture, a Reflection session, and an optional Studio session. 8 | 9 | ## Prerequisites 10 | 11 | No prerequisite knowledge. No programming experience is needed. People who already have programmed are likely to get a new perspective on what programming can be. You will use your own computing device: laptop or large tablet with an internet browser (Chrome, Firefox, or MS Edge). Internet connectivity is required. 12 | 13 | ## Each day 14 | 15 | Each day will start with an online lecture of about 1 hour and 45 minutes, starting at 10am. There will be an online Reflection session of one hour starting at 4pm that will include group discussion, individual programming exercises, and guided pair programming. For extra fun, an experienced assistant will facilitate optional 2-hour online Studio sessions in small groups each evening from 7pm to 9pm. 16 | 17 | ## Schedule 18 | 19 | Design your own course: feel free to come on any of the days, consistent with the dependencies shown below. 20 | 21 | Day 1, Tuesday, January 18: The elements: See the basic ingredients of all computer programs 22 | 23 | Day 2, Wednesday, January 19: A picture language: Program graphical patterns by wishful thinking 24 | Depends on: Day 1 25 | 26 | Day 3, Friday, January 21: Functions: Experience the magic of higher-order programming 27 | Depends on: Days 1 and 2 28 | 29 | Day 4, Tuesday, January 25: A curve language: Program fractals and three-dimensional curves with functions 30 | Depends on: Days 1-3 31 | 32 | Day 5, Wednesday, January 26: The lambda calculus: Explore the essence of computation 33 | Depends on: Days 1-3 34 | 35 | Day 6, Friday, January 28: Functional audio processing: Make some noise 36 | Depends on: Days 1-3 37 | (equipment: bring a stereo headset that works with your browser) 38 | 39 | ## Course links 40 | 41 | The [course calendar](https://calendar.google.com/calendar/embed?src=r778j04ilipi67b03u6dk665es%40group.calendar.google.com&ctz=America%2FNew_York) has all links to zoom sessions, recordings, slides, and other material. 42 | 43 | 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-ShareAlike 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-ShareAlike 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. Share means to provide material to the public by any means or 126 | process that requires permission under the Licensed Rights, such 127 | as reproduction, public display, public performance, distribution, 128 | dissemination, communication, or importation, and to make material 129 | available to the public including in ways that members of the 130 | public may access the material from a place and at a time 131 | individually chosen by them. 132 | 133 | l. Sui Generis Database Rights means rights other than copyright 134 | resulting from Directive 96/9/EC of the European Parliament and of 135 | the Council of 11 March 1996 on the legal protection of databases, 136 | as amended and/or succeeded, as well as other essentially 137 | equivalent rights anywhere in the world. 138 | 139 | m. You means the individual or entity exercising the Licensed Rights 140 | under this Public License. Your has a corresponding meaning. 141 | 142 | 143 | Section 2 -- Scope. 144 | 145 | a. License grant. 146 | 147 | 1. Subject to the terms and conditions of this Public License, 148 | the Licensor hereby grants You a worldwide, royalty-free, 149 | non-sublicensable, non-exclusive, irrevocable license to 150 | exercise the Licensed Rights in the Licensed Material to: 151 | 152 | a. reproduce and Share the Licensed Material, in whole or 153 | in part; and 154 | 155 | b. produce, reproduce, and Share Adapted Material. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. Additional offer from the Licensor -- Adapted Material. 186 | Every recipient of Adapted Material from You 187 | automatically receives an offer from the Licensor to 188 | exercise the Licensed Rights in the Adapted Material 189 | under the conditions of the Adapter's License You apply. 190 | 191 | c. No downstream restrictions. You may not offer or impose 192 | any additional or different terms or conditions on, or 193 | apply any Effective Technological Measures to, the 194 | Licensed Material if doing so restricts exercise of the 195 | Licensed Rights by any recipient of the Licensed 196 | Material. 197 | 198 | 6. No endorsement. Nothing in this Public License constitutes or 199 | may be construed as permission to assert or imply that You 200 | are, or that Your use of the Licensed Material is, connected 201 | with, or sponsored, endorsed, or granted official status by, 202 | the Licensor or others designated to receive attribution as 203 | provided in Section 3(a)(1)(A)(i). 204 | 205 | b. Other rights. 206 | 207 | 1. Moral rights, such as the right of integrity, are not 208 | licensed under this Public License, nor are publicity, 209 | privacy, and/or other similar personality rights; however, to 210 | the extent possible, the Licensor waives and/or agrees not to 211 | assert any such rights held by the Licensor to the limited 212 | extent necessary to allow You to exercise the Licensed 213 | Rights, but not otherwise. 214 | 215 | 2. Patent and trademark rights are not licensed under this 216 | Public License. 217 | 218 | 3. To the extent possible, the Licensor waives any right to 219 | collect royalties from You for the exercise of the Licensed 220 | Rights, whether directly or through a collecting society 221 | under any voluntary or waivable statutory or compulsory 222 | licensing scheme. In all other cases the Licensor expressly 223 | reserves any right to collect such royalties. 224 | 225 | 226 | Section 3 -- License Conditions. 227 | 228 | Your exercise of the Licensed Rights is expressly made subject to the 229 | following conditions. 230 | 231 | a. Attribution. 232 | 233 | 1. If You Share the Licensed Material (including in modified 234 | form), You must: 235 | 236 | a. retain the following if it is supplied by the Licensor 237 | with the Licensed Material: 238 | 239 | i. identification of the creator(s) of the Licensed 240 | Material and any others designated to receive 241 | attribution, in any reasonable manner requested by 242 | the Licensor (including by pseudonym if 243 | designated); 244 | 245 | ii. a copyright notice; 246 | 247 | iii. a notice that refers to this Public License; 248 | 249 | iv. a notice that refers to the disclaimer of 250 | warranties; 251 | 252 | v. a URI or hyperlink to the Licensed Material to the 253 | extent reasonably practicable; 254 | 255 | b. indicate if You modified the Licensed Material and 256 | retain an indication of any previous modifications; and 257 | 258 | c. indicate the Licensed Material is licensed under this 259 | Public License, and include the text of, or the URI or 260 | hyperlink to, this Public License. 261 | 262 | 2. You may satisfy the conditions in Section 3(a)(1) in any 263 | reasonable manner based on the medium, means, and context in 264 | which You Share the Licensed Material. For example, it may be 265 | reasonable to satisfy the conditions by providing a URI or 266 | hyperlink to a resource that includes the required 267 | information. 268 | 269 | 3. If requested by the Licensor, You must remove any of the 270 | information required by Section 3(a)(1)(A) to the extent 271 | reasonably practicable. 272 | 273 | b. ShareAlike. 274 | 275 | In addition to the conditions in Section 3(a), if You Share 276 | Adapted Material You produce, the following conditions also apply. 277 | 278 | 1. The Adapter's License You apply must be a Creative Commons 279 | license with the same License Elements, this version or 280 | later, or a BY-SA Compatible License. 281 | 282 | 2. You must include the text of, or the URI or hyperlink to, the 283 | Adapter's License You apply. You may satisfy this condition 284 | in any reasonable manner based on the medium, means, and 285 | context in which You Share Adapted Material. 286 | 287 | 3. You may not offer or impose any additional or different terms 288 | or conditions on, or apply any Effective Technological 289 | Measures to, Adapted Material that restrict exercise of the 290 | rights granted under the Adapter's License You apply. 291 | 292 | 293 | Section 4 -- Sui Generis Database Rights. 294 | 295 | Where the Licensed Rights include Sui Generis Database Rights that 296 | apply to Your use of the Licensed Material: 297 | 298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 299 | to extract, reuse, reproduce, and Share all or a substantial 300 | portion of the contents of the database; 301 | 302 | b. if You include all or a substantial portion of the database 303 | contents in a database in which You have Sui Generis Database 304 | Rights, then the database in which You have Sui Generis Database 305 | Rights (but not its individual contents) is Adapted Material, 306 | 307 | including for purposes of Section 3(b); and 308 | c. You must comply with the conditions in Section 3(a) if You Share 309 | all or a substantial portion of the contents of the database. 310 | 311 | For the avoidance of doubt, this Section 4 supplements and does not 312 | replace Your obligations under this Public License where the Licensed 313 | Rights include other Copyright and Similar Rights. 314 | 315 | 316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 317 | 318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 328 | 329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 338 | 339 | c. The disclaimer of warranties and limitation of liability provided 340 | above shall be interpreted in a manner that, to the extent 341 | possible, most closely approximates an absolute disclaimer and 342 | waiver of all liability. 343 | 344 | 345 | Section 6 -- Term and Termination. 346 | 347 | a. This Public License applies for the term of the Copyright and 348 | Similar Rights licensed here. However, if You fail to comply with 349 | this Public License, then Your rights under this Public License 350 | terminate automatically. 351 | 352 | b. Where Your right to use the Licensed Material has terminated under 353 | Section 6(a), it reinstates: 354 | 355 | 1. automatically as of the date the violation is cured, provided 356 | it is cured within 30 days of Your discovery of the 357 | violation; or 358 | 359 | 2. upon express reinstatement by the Licensor. 360 | 361 | For the avoidance of doubt, this Section 6(b) does not affect any 362 | right the Licensor may have to seek remedies for Your violations 363 | of this Public License. 364 | 365 | c. For the avoidance of doubt, the Licensor may also offer the 366 | Licensed Material under separate terms or conditions or stop 367 | distributing the Licensed Material at any time; however, doing so 368 | will not terminate this Public License. 369 | 370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 371 | License. 372 | 373 | 374 | Section 7 -- Other Terms and Conditions. 375 | 376 | a. The Licensor shall not be bound by any additional or different 377 | terms or conditions communicated by You unless expressly agreed. 378 | 379 | b. Any arrangements, understandings, or agreements regarding the 380 | Licensed Material not stated herein are separate from and 381 | independent of the terms and conditions of this Public License. 382 | 383 | 384 | Section 8 -- Interpretation. 385 | 386 | a. For the avoidance of doubt, this Public License does not, and 387 | shall not be interpreted to, reduce, limit, restrict, or impose 388 | conditions on any use of the Licensed Material that could lawfully 389 | be made without permission under this Public License. 390 | 391 | b. To the extent possible, if any provision of this Public License is 392 | deemed unenforceable, it shall be automatically reformed to the 393 | minimum extent necessary to make it enforceable. If the provision 394 | cannot be reformed, it shall be severed from this Public License 395 | without affecting the enforceability of the remaining terms and 396 | conditions. 397 | 398 | c. No term or condition of this Public License will be waived and no 399 | failure to comply consented to unless expressly agreed to by the 400 | Licensor. 401 | 402 | d. Nothing in this Public License constitutes or may be interpreted 403 | as a limitation upon, or waiver of, any privileges and immunities 404 | that apply to the Licensor or You, including from the legal 405 | processes of any jurisdiction or authority. 406 | 407 | 408 | ======================================================================= 409 | 410 | Creative Commons is not a party to its public 411 | licenses. Notwithstanding, Creative Commons may elect to apply one of 412 | its public licenses to material it publishes and in those instances 413 | will be considered the “Licensor.” The text of the Creative Commons 414 | public licenses is dedicated to the public domain under the CC0 Public 415 | Domain Dedication. Except for the limited purpose of indicating that 416 | material is shared under a Creative Commons public license or as 417 | otherwise permitted by the Creative Commons policies published at 418 | creativecommons.org/policies, Creative Commons does not authorize the 419 | use of the trademark "Creative Commons" or any other trademark or logo 420 | of Creative Commons without its prior written consent including, 421 | without limitation, in connection with any unauthorized modifications 422 | to any of its public licenses or any other arrangements, 423 | understandings, or agreements concerning use of licensed material. For 424 | the avoidance of doubt, this paragraph does not form part of the 425 | public licenses. 426 | 427 | Creative Commons may be contacted at creativecommons.org. 428 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Source Academy](https://sourceacademy.org) is an online experiential environment for computational thinking. Developed for courses that use the book [*Structure and Interpretation of Computer Programs, JavaScript Edition*](https://sourceacademy.org/sicpjs/index) (SICP JS), the environment is currently supporting TypeScript and JavaScript, and educational sublanguages of Java, C, Python, and Scheme. Here you find resources for [learners and educators who use SICP JS](https://about.sourceacademy.org/learner/README.html), for [developers](https://about.sourceacademy.org/developer/README.html), and for educational [researchers](https://about.sourceacademy.org/research/README.html). 2 | 3 | To get an idea of the environment and developer community, watch the videos of our 4 | * [SIGCSE TS 2023 Source Academy demo](https://www.youtube.com/watch?v=s_UPhAT25fo) and 5 | * [SIGCSE TS 2023 paper presentation](https://www.youtube.com/watch?v=herwKTpNeDE). 6 | 7 | ----------------- 8 | 9 | Our mission is to *expose the beauty and fun in computational thinking, and make them universally accessible*. 10 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely edit after that. If you find 5 | # yourself editing this file very often, consider using Jekyll's data files 6 | # feature for the data you need to update frequently. 7 | # 8 | # For technical reasons, this file is *NOT* reloaded automatically when you use 9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process. 10 | # 11 | # If you need help with YAML syntax, here are some quick references for you: 12 | # https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml 13 | # https://learnxinyminutes.com/docs/yaml/ 14 | # 15 | # Site settings 16 | # These are used to personalize your new site. If you look in the HTML files, 17 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. 18 | # You can create any custom variable you would like, and they will be accessible 19 | # in the templates via {{ site.myvariable }}. 20 | 21 | title: Source Academy 22 | description: >- # this means to ignore newlines until "baseurl:" 23 | Info on Source Academy for learners, educators, developers, and researchers 24 | baseurl: "" # the subpath of your site, e.g. /blog 25 | url: "https://about.sourceacademy.org" # the base hostname & protocol for your site, e.g. http://example.com 26 | github_username: source-academy 27 | github_repo_name: general 28 | github_repo_link: https://github.com/source-academy/general 29 | 30 | # Header Pages 31 | header_pages: 32 | - learner/README.md 33 | - developer/README.md 34 | - research/README.md 35 | - accolade/README.md 36 | 37 | # Build settings 38 | theme: jekyll-theme-minimal 39 | plugins: 40 | - jekyll-feed 41 | 42 | # Exclude from processing. 43 | # The following items will not be processed, by default. 44 | # Any item listed under the `exclude:` key here will be automatically added to 45 | # the internal "default list". 46 | # 47 | # Excluded items can be processed by explicitly listing the directories or 48 | # their entries' file path in the `include:` list. 49 | # 50 | # exclude: 51 | # - .sass-cache/ 52 | # - .jekyll-cache/ 53 | # - gemfiles/ 54 | # - Gemfile 55 | # - Gemfile.lock 56 | # - node_modules/ 57 | # - vendor/bundle/ 58 | # - vendor/cache/ 59 | # - vendor/gems/ 60 | # - vendor/ruby/ 61 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {%- seo -%} 6 | 7 | 8 | {%- feed_meta -%} 9 | {%- if jekyll.environment == 'production' and site.google_analytics -%} 10 | {%- include google-analytics.html -%} 11 | {%- endif -%} 12 | 13 | -------------------------------------------------------------------------------- /_includes/header.html: -------------------------------------------------------------------------------- 1 | 36 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {%- include head.html -%} 5 | 6 | 7 | 8 | {%- include header.html -%} 9 | 10 |
11 |
12 | {{ content }} 13 |
14 |
15 | 16 | 17 | 18 | {%- include footer.html -%} 19 | 20 | 21 | -------------------------------------------------------------------------------- /_sass/minima.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | // Define defaults for each variable. 4 | 5 | $base-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default; 6 | $base-font-size: 16px !default; 7 | $base-font-weight: 400 !default; 8 | $small-font-size: $base-font-size * 0.875 !default; 9 | $base-line-height: 1.5 !default; 10 | 11 | $spacing-unit: 30px !default; 12 | 13 | $text-color: #111 !default; 14 | $background-color: #fdfdfd !default; 15 | $brand-color: #2a7ae2 !default; 16 | 17 | $grey-color: #828282 !default; 18 | $grey-color-light: lighten($grey-color, 40%) !default; 19 | $grey-color-dark: darken($grey-color, 25%) !default; 20 | 21 | $table-text-align: left !default; 22 | 23 | // Width of the content area 24 | $content-width: 800px !default; 25 | 26 | $on-palm: 600px !default; 27 | $on-laptop: 800px !default; 28 | 29 | // Use media queries like this: 30 | // @include media-query($on-palm) { 31 | // .wrapper { 32 | // padding-right: $spacing-unit / 2; 33 | // padding-left: $spacing-unit / 2; 34 | // } 35 | // } 36 | @mixin media-query($device) { 37 | @media screen and (max-width: $device) { 38 | @content; 39 | } 40 | } 41 | 42 | @mixin relative-font-size($ratio) { 43 | font-size: $base-font-size * $ratio; 44 | } 45 | 46 | // Import partials. 47 | @import 48 | "minima/base", 49 | "minima/layout", 50 | "minima/syntax-highlighting" 51 | ; 52 | -------------------------------------------------------------------------------- /_sass/minima/_base.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Reset some basic elements 3 | */ 4 | body, h1, h2, h3, h4, h5, h6, 5 | p, blockquote, pre, hr, 6 | dl, dd, ol, ul, figure { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | 12 | 13 | /** 14 | * Basic styling 15 | */ 16 | body { 17 | font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family; 18 | color: $text-color; 19 | background-color: $background-color; 20 | -webkit-text-size-adjust: 100%; 21 | -webkit-font-feature-settings: "kern" 1; 22 | -moz-font-feature-settings: "kern" 1; 23 | -o-font-feature-settings: "kern" 1; 24 | font-feature-settings: "kern" 1; 25 | font-kerning: normal; 26 | display: flex; 27 | min-height: 100vh; 28 | flex-direction: column; 29 | } 30 | 31 | 32 | 33 | /** 34 | * Set `margin-bottom` to maintain vertical rhythm 35 | */ 36 | h1, h2, h3, h4, h5, h6, 37 | p, blockquote, pre, 38 | ul, ol, dl, figure, 39 | %vertical-rhythm { 40 | margin-bottom: $spacing-unit / 2; 41 | } 42 | 43 | 44 | 45 | /** 46 | * `main` element 47 | */ 48 | main { 49 | display: block; /* Default value of `display` of `main` element is 'inline' in IE 11. */ 50 | } 51 | 52 | 53 | 54 | /** 55 | * Images 56 | */ 57 | img { 58 | max-width: 100%; 59 | vertical-align: middle; 60 | } 61 | 62 | 63 | 64 | /** 65 | * Figures 66 | */ 67 | figure > img { 68 | display: block; 69 | } 70 | 71 | figcaption { 72 | font-size: $small-font-size; 73 | } 74 | 75 | 76 | 77 | /** 78 | * Lists 79 | */ 80 | ul, ol { 81 | margin-left: $spacing-unit; 82 | } 83 | 84 | li { 85 | > ul, 86 | > ol { 87 | margin-bottom: 0; 88 | } 89 | } 90 | 91 | 92 | 93 | /** 94 | * Headings 95 | */ 96 | h1, h2, h3, h4, h5, h6 { 97 | font-weight: $base-font-weight; 98 | } 99 | 100 | 101 | 102 | /** 103 | * Links 104 | */ 105 | a { 106 | color: $brand-color; 107 | text-decoration: none; 108 | 109 | &:visited { 110 | color: darken($brand-color, 15%); 111 | } 112 | 113 | &:hover { 114 | color: $text-color; 115 | text-decoration: underline; 116 | } 117 | 118 | .social-media-list &:hover { 119 | text-decoration: none; 120 | 121 | .username { 122 | text-decoration: underline; 123 | } 124 | } 125 | } 126 | 127 | 128 | /** 129 | * Blockquotes 130 | */ 131 | blockquote { 132 | color: $grey-color; 133 | border-left: 4px solid $grey-color-light; 134 | padding-left: $spacing-unit / 2; 135 | @include relative-font-size(1.125); 136 | letter-spacing: -1px; 137 | font-style: italic; 138 | 139 | > :last-child { 140 | margin-bottom: 0; 141 | } 142 | } 143 | 144 | 145 | 146 | /** 147 | * Code formatting 148 | */ 149 | pre, 150 | code { 151 | @include relative-font-size(0.9375); 152 | border: 1px solid $grey-color-light; 153 | border-radius: 3px; 154 | background-color: #eef; 155 | } 156 | 157 | code { 158 | padding: 1px 5px; 159 | } 160 | 161 | pre { 162 | padding: 8px 12px; 163 | overflow-x: auto; 164 | 165 | > code { 166 | border: 0; 167 | padding-right: 0; 168 | padding-left: 0; 169 | } 170 | } 171 | 172 | 173 | 174 | /** 175 | * Wrapper 176 | */ 177 | .wrapper { 178 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2)); 179 | max-width: calc(#{$content-width} - (#{$spacing-unit} * 2)); 180 | margin-right: auto; 181 | margin-left: auto; 182 | padding-right: $spacing-unit; 183 | padding-left: $spacing-unit; 184 | @extend %clearfix; 185 | 186 | @include media-query($on-laptop) { 187 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit})); 188 | max-width: calc(#{$content-width} - (#{$spacing-unit})); 189 | padding-right: $spacing-unit / 2; 190 | padding-left: $spacing-unit / 2; 191 | } 192 | } 193 | 194 | 195 | 196 | /** 197 | * Clearfix 198 | */ 199 | %clearfix:after { 200 | content: ""; 201 | display: table; 202 | clear: both; 203 | } 204 | 205 | 206 | 207 | /** 208 | * Icons 209 | */ 210 | 211 | .svg-icon { 212 | width: 16px; 213 | height: 16px; 214 | display: inline-block; 215 | fill: #{$grey-color}; 216 | padding-right: 5px; 217 | vertical-align: text-top; 218 | } 219 | 220 | .social-media-list { 221 | li + li { 222 | padding-top: 5px; 223 | } 224 | } 225 | 226 | 227 | 228 | /** 229 | * Tables 230 | */ 231 | table { 232 | margin-bottom: $spacing-unit; 233 | width: 100%; 234 | text-align: $table-text-align; 235 | color: lighten($text-color, 18%); 236 | border-collapse: collapse; 237 | border: 1px solid $grey-color-light; 238 | tr { 239 | &:nth-child(even) { 240 | background-color: lighten($grey-color-light, 6%); 241 | } 242 | } 243 | th, td { 244 | padding: ($spacing-unit / 3) ($spacing-unit / 2); 245 | } 246 | th { 247 | background-color: lighten($grey-color-light, 3%); 248 | border: 1px solid darken($grey-color-light, 4%); 249 | border-bottom-color: darken($grey-color-light, 12%); 250 | } 251 | td { 252 | border: 1px solid $grey-color-light; 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /_sass/minima/_layout.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Site header 3 | */ 4 | .site-header { 5 | border-top: 5px solid $grey-color-dark; 6 | border-bottom: 1px solid $grey-color-light; 7 | min-height: $spacing-unit * 1.865; 8 | 9 | // Positioning context for the mobile navigation icon 10 | position: relative; 11 | } 12 | 13 | .site-logo-and-title { 14 | display: flex; 15 | align-items: center; 16 | width: fit-content; 17 | float: left; 18 | } 19 | 20 | .site-logo { 21 | width: 32px; 22 | height: 32px; 23 | } 24 | 25 | .site-title { 26 | @include relative-font-size(1.625); 27 | font-weight: 300; 28 | line-height: $base-line-height * $base-font-size * 2.25; 29 | letter-spacing: -1px; 30 | margin-bottom: 0; 31 | 32 | &, 33 | &:visited { 34 | color: $grey-color-dark; 35 | } 36 | } 37 | 38 | .site-nav { 39 | float: right; 40 | line-height: $base-line-height * $base-font-size * 2.25; 41 | 42 | .nav-trigger { 43 | display: none; 44 | } 45 | 46 | .menu-icon { 47 | display: none; 48 | } 49 | 50 | .page-link { 51 | color: $text-color; 52 | line-height: $base-line-height; 53 | 54 | // Gaps between nav items, but not on the last one 55 | &:not(:last-child) { 56 | margin-right: 20px; 57 | } 58 | } 59 | 60 | @include media-query($on-palm) { 61 | position: absolute; 62 | top: 9px; 63 | right: $spacing-unit / 2; 64 | background-color: $background-color; 65 | border: 1px solid $grey-color-light; 66 | border-radius: 5px; 67 | text-align: right; 68 | 69 | label[for="nav-trigger"] { 70 | display: block; 71 | float: right; 72 | width: 36px; 73 | height: 36px; 74 | z-index: 2; 75 | cursor: pointer; 76 | } 77 | 78 | .menu-icon { 79 | display: block; 80 | float: right; 81 | width: 36px; 82 | height: 26px; 83 | line-height: 0; 84 | padding-top: 10px; 85 | text-align: center; 86 | 87 | > svg { 88 | fill: $grey-color-dark; 89 | } 90 | } 91 | 92 | input ~ .trigger { 93 | clear: both; 94 | display: none; 95 | } 96 | 97 | input:checked ~ .trigger { 98 | display: block; 99 | padding-bottom: 5px; 100 | } 101 | 102 | .page-link { 103 | display: block; 104 | padding: 5px 10px; 105 | 106 | &:not(:last-child) { 107 | margin-right: 0; 108 | } 109 | margin-left: 20px; 110 | } 111 | } 112 | } 113 | 114 | /** 115 | * Site footer 116 | */ 117 | .site-footer { 118 | border-top: 1px solid $grey-color-light; 119 | padding: $spacing-unit 0; 120 | display: flex; 121 | justify-content: center; 122 | } 123 | 124 | .footer-heading { 125 | @include relative-font-size(1.125); 126 | margin-bottom: $spacing-unit / 2; 127 | } 128 | 129 | .contact-list, 130 | .social-media-list { 131 | list-style: none; 132 | margin-left: 0; 133 | } 134 | 135 | .footer-col-wrapper { 136 | @include relative-font-size(0.9375); 137 | color: $grey-color; 138 | margin-left: -$spacing-unit / 2; 139 | @extend %clearfix; 140 | } 141 | 142 | .footer-col { 143 | float: left; 144 | margin-bottom: $spacing-unit / 2; 145 | padding-left: $spacing-unit / 2; 146 | } 147 | 148 | .footer-col-1 { 149 | width: -webkit-calc(35% - (#{$spacing-unit} / 2)); 150 | width: calc(35% - (#{$spacing-unit} / 2)); 151 | } 152 | 153 | .footer-col-2 { 154 | width: -webkit-calc(20% - (#{$spacing-unit} / 2)); 155 | width: calc(20% - (#{$spacing-unit} / 2)); 156 | } 157 | 158 | .footer-col-3 { 159 | width: -webkit-calc(45% - (#{$spacing-unit} / 2)); 160 | width: calc(45% - (#{$spacing-unit} / 2)); 161 | } 162 | 163 | @include media-query($on-laptop) { 164 | .footer-col-1, 165 | .footer-col-2 { 166 | width: -webkit-calc(50% - (#{$spacing-unit} / 2)); 167 | width: calc(50% - (#{$spacing-unit} / 2)); 168 | } 169 | 170 | .footer-col-3 { 171 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 172 | width: calc(100% - (#{$spacing-unit} / 2)); 173 | } 174 | } 175 | 176 | @include media-query($on-palm) { 177 | .footer-col { 178 | float: none; 179 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 180 | width: calc(100% - (#{$spacing-unit} / 2)); 181 | } 182 | } 183 | 184 | /** 185 | * Page content 186 | */ 187 | .page-content { 188 | padding: $spacing-unit 0; 189 | flex: 1; 190 | } 191 | 192 | .page-heading { 193 | @include relative-font-size(2); 194 | } 195 | 196 | .post-list-heading { 197 | @include relative-font-size(1.75); 198 | } 199 | 200 | .post-list { 201 | margin-left: 0; 202 | list-style: none; 203 | 204 | > li { 205 | margin-bottom: $spacing-unit; 206 | } 207 | } 208 | 209 | .post-meta { 210 | font-size: $small-font-size; 211 | color: $grey-color; 212 | } 213 | 214 | .post-link { 215 | display: block; 216 | @include relative-font-size(1.5); 217 | } 218 | -------------------------------------------------------------------------------- /_sass/minima/_syntax-highlighting.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Syntax highlighting styles 3 | */ 4 | .highlight { 5 | background: #fff; 6 | @extend %vertical-rhythm; 7 | 8 | .highlighter-rouge & { 9 | background: #eef; 10 | } 11 | 12 | .c { color: #998; font-style: italic } // Comment 13 | .err { color: #a61717; background-color: #e3d2d2 } // Error 14 | .k { font-weight: bold } // Keyword 15 | .o { font-weight: bold } // Operator 16 | .cm { color: #998; font-style: italic } // Comment.Multiline 17 | .cp { color: #999; font-weight: bold } // Comment.Preproc 18 | .c1 { color: #998; font-style: italic } // Comment.Single 19 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special 20 | .gd { color: #000; background-color: #fdd } // Generic.Deleted 21 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific 22 | .ge { font-style: italic } // Generic.Emph 23 | .gr { color: #a00 } // Generic.Error 24 | .gh { color: #999 } // Generic.Heading 25 | .gi { color: #000; background-color: #dfd } // Generic.Inserted 26 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific 27 | .go { color: #888 } // Generic.Output 28 | .gp { color: #555 } // Generic.Prompt 29 | .gs { font-weight: bold } // Generic.Strong 30 | .gu { color: #aaa } // Generic.Subheading 31 | .gt { color: #a00 } // Generic.Traceback 32 | .kc { font-weight: bold } // Keyword.Constant 33 | .kd { font-weight: bold } // Keyword.Declaration 34 | .kp { font-weight: bold } // Keyword.Pseudo 35 | .kr { font-weight: bold } // Keyword.Reserved 36 | .kt { color: #458; font-weight: bold } // Keyword.Type 37 | .m { color: #099 } // Literal.Number 38 | .s { color: #d14 } // Literal.String 39 | .na { color: #008080 } // Name.Attribute 40 | .nb { color: #0086B3 } // Name.Builtin 41 | .nc { color: #458; font-weight: bold } // Name.Class 42 | .no { color: #008080 } // Name.Constant 43 | .ni { color: #800080 } // Name.Entity 44 | .ne { color: #900; font-weight: bold } // Name.Exception 45 | .nf { color: #900; font-weight: bold } // Name.Function 46 | .nn { color: #555 } // Name.Namespace 47 | .nt { color: #000080 } // Name.Tag 48 | .nv { color: #008080 } // Name.Variable 49 | .ow { font-weight: bold } // Operator.Word 50 | .w { color: #bbb } // Text.Whitespace 51 | .mf { color: #099 } // Literal.Number.Float 52 | .mh { color: #099 } // Literal.Number.Hex 53 | .mi { color: #099 } // Literal.Number.Integer 54 | .mo { color: #099 } // Literal.Number.Oct 55 | .sb { color: #d14 } // Literal.String.Backtick 56 | .sc { color: #d14 } // Literal.String.Char 57 | .sd { color: #d14 } // Literal.String.Doc 58 | .s2 { color: #d14 } // Literal.String.Double 59 | .se { color: #d14 } // Literal.String.Escape 60 | .sh { color: #d14 } // Literal.String.Heredoc 61 | .si { color: #d14 } // Literal.String.Interpol 62 | .sx { color: #d14 } // Literal.String.Other 63 | .sr { color: #009926 } // Literal.String.Regex 64 | .s1 { color: #d14 } // Literal.String.Single 65 | .ss { color: #990073 } // Literal.String.Symbol 66 | .bp { color: #999 } // Name.Builtin.Pseudo 67 | .vc { color: #008080 } // Name.Variable.Class 68 | .vg { color: #008080 } // Name.Variable.Global 69 | .vi { color: #008080 } // Name.Variable.Instance 70 | .il { color: #099 } // Literal.Number.Integer.Long 71 | } 72 | -------------------------------------------------------------------------------- /accolade/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | label: Praise 3 | --- 4 | 5 | # Endorsements of Source Academy 6 | 7 | - "Source Academy was a brilliant and fun platform to use. The format of paths, missions, and quests kept my interest up throughout the course." 8 | a student of CS1101S at the National University of Singapore in 2021 9 | - "The Source Academy was nothing short of a marvel; I cannot imagine the amount of effort and resources that were needed to make it a success..." 10 | a student of CS1101S at the National University of Singapore in 2020 11 | - "I had previously had vague notions of trying to teach a course based on 'Structure and Interpretation of Computer Programs', but using JavaScript rather than Scheme for a while, but it always seemed too daunting. Then, one day, I discovered the 'SICP JavaScipt Edition', Source Academy and Martin Henz's course. I'm sure I would never have taught my course if not for the existence of those resources. Moreover, I could not have been effective in teaching the course if not for the extraordinary level of support and advice from Martin Henz personally, as well as from his Source Academy staff. They helped me set up my own servers running the software, gave advice on how to use the software and run an effective course. They were also extremely responsive to bug reports and feature requests during the entire course of my teaching." 12 | Mark Friedman, University of San Francisco. 2021 13 | 14 | # Endorsements of SICP JS 15 | 16 | - “A classic, meticulously revisited and modernized with talent, pedagogy, and substance. Thank you, Martin, Tobias, and Julie!” 17 | Olivier Danvy, Yale-NUS College 18 | - “When I am asked 'How can I become a better programmer?,' I recommend this book.” 19 | Douglas Crockford, author of How JavaScript Works 20 | - “How much is a programming book influenced by its programming language? SICP in JavaScript is remarkably fluid, an excellent choice for today's programmers.” 21 | Peter Van Roy, Université catholique de Louvain 22 | - "Henz and Wrigstad have created a small masterpiece: the book reads as if it had always been written for JavaScript. For many young developers, reading SICP should now be much more interesting than before. The easy-to-understand English also invites easy reading." 23 | [c't – Magazin für Computertechnik](https://github.com/source-academy/general/raw/master/accolade/ct-review-sicp-js.png) (Magazine for Computer Technology, [English translation](https://github.com/source-academy/general/raw/master/accolade/ct-english.txt)) 24 | 25 | 26 | # Awards 27 | 28 | - [OCP 2022/2023](https://www.comp.nus.edu.sg/programmes/ug/honour/faculty/): [Zhao Jingjing](https://github.com/zhaojj2209) won the Outstanding Computing Project Prize AY2022/2023 at the National University of Singapore for web-programming support in Source Academy 29 | - [OCP 2022/2023](https://www.comp.nus.edu.sg/programmes/ug/honour/faculty/): [Ian Yong](https://github.com/ianyong) won the Outstanding Computing Project Prize AY2022/2023 at the National University of Singapore for multi-file support in Source Academy 30 | - geNiUSbook Competition 2022 Consolation Prize: [Samuel Fang](https://github.com/samuelfangjw) and [Martin Henz](https://github.com/martin-henz) won the genNiUSbook Competition 2022 Consolation Prize, for [Interactive SICP JS](https://sourceacademy.org/sicpjs) at the National University of Singapore 31 | - OURP 2021/22: [Source Academy Student Team Rook](https://sourceacademy.org/contributors) 32 | (Tee Hao Wei, Chow En Rong, Chen Yanyu, Samuel Fang, Gokul Rajiv, Lee Hyung Woon, Shen Yi Hong, Thomas Tan Chee Kun, Bryan Loh, Marcus Tang Xin Kye) 33 | won the [Outstanding Undergraduate Researcher Prize](https://www.nus.edu.sg/registrar/academic-information-policies/education-at-nus/medals-and-prizes-(university-level)/rules-of-award---o) 2021/22 (Group category) at the National University of Singapore 34 | - [ADEA 2021](https://nus.edu.sg/cdtl/teaching-and-learning-quality/teaching-awards/teaching-award-winners#ATEA%20Winners): The [Source Academy Teams Cadet and Knight](https://sourceacademy.org/contributors) 35 | (Martin HENZ, 36 | LOW Kok Lim, 37 | Boyd ANDERSON, 38 | Eldric LIEW Chun Tze, 39 | Evan SEBASTIAN, 40 | NG Tse Pei, 41 | Joey YEO, 42 | TAN Yu Wei, 43 | Julius Putra Tanu SETIAJI, 44 | LEE Ning Yuan, 45 | Vignesh SHANKAR, 46 | Thomas TAN, 47 | CHEN Shaowei, 48 | LIOW Jia Chen, 49 | GE Shuming, 50 | Rahul RAJESH, 51 | Daryl TAN, 52 | SHE Jiayu, 53 | Tiffany CHONG, 54 | Anthony HALIM, 55 | TEE Hao Wei, 56 | Jet KAN Yip Keng, 57 | Sean LOW Jun Kai, 58 | Sigmund CHIANASTA) 59 | won the [Annual Digital Eduation Award](https://www.nus.edu.sg/cdtl/teaching-and-learning-quality/teaching-awards/types-of-awards/nus-annual-digital-education-award) 2021 (Team category) at the National University of Singapore 60 | - [People's Choice Award, geNiUSbook 2021](https://credentials.nus.edu.sg/7db4ddae-a789-434f-91d9-d48bab9bb50f): [Samuel Fang](https://github.com/samuelfangjw) and [Martin Henz](https://github.com/martin-henz) won the People's Choice Award, genNiUSbook 2021, for [Interactive SICP JS](https://sourceacademy.org/sicpjs) (most popular e-book) at the National University of Singapore 61 | -------------------------------------------------------------------------------- /accolade/ct-english.txt: -------------------------------------------------------------------------------- 1 | More than cosmetics 2 | 3 | Nothing in IT is as constant as change. In some domains, however, hypes do not play a major role. This includes the fundamentals of good programming and solid software design. A standard work on this is now available in an easily accessible edition for JavaScript. 4 | 5 | Since 1996, the second edition of “Structure and Interpretation of Computer Programs” (SICP) by Abelson and the Sussmans has been explaining what maintainable and extensible code should look like. The only shortcoming of the classic: the authors used the less common LISP dialect MIT Scheme for their program examples. This presented a hurdle for many potential readers. Martin Henz and Tobias Wrigstad have now ported the text and all examples to JavaScript. This is familiar to many and makes reading more accessible. But you can definitely see an irony of history in this, because JavaScript is basically very similar to Scheme. 6 | 7 | The two made the changes very carefully, so that there are no differences in content to the original. Furthermore, the original authors introduce functional programming in an almost playful way. The first snippets of code solve minor problems in number theory and numerics, but the complexity quickly increases. 8 | 9 | Besides a package for the symbolic derivation of functions, the authors implement a system for processing symbolic algebra with polynomials and a simulator for electronic circuits. They are also developing a JavaScript interpreter that can process the code examples from the book. Numerous – sometimes challenging – exercises help to deepen the material. 10 | 11 | The syntactic minimalism is consistently impressive. All code uses constants, functions, and the ternary operator almost exclusively. You rarely find an if statement and the first assignment to a variable comes after almost 200 pages. The text is thus a plea for the merits of functional programming over the imperative alternative. 12 | 13 | Henz and Wrigstad have created a small masterpiece: the book reads as if it had always been written for JavaScript. For many young developers, reading SICP should now be much more interesting than before. The easy-to-understand English also invites easy reading. 14 | -------------------------------------------------------------------------------- /accolade/ct-review-sicp-js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/general/be4e540a232d540ca7fe7bcdc3f56d9589376667/accolade/ct-review-sicp-js.png -------------------------------------------------------------------------------- /assets/main.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # Only the main Sass file needs front matter (the dashes are enough) 3 | --- 4 | 5 | @import "minima"; 6 | -------------------------------------------------------------------------------- /assets/sourcepower.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/source-academy/general/be4e540a232d540ca7fe7bcdc3f56d9589376667/assets/sourcepower.ico -------------------------------------------------------------------------------- /deployment/README.md: -------------------------------------------------------------------------------- 1 | # Deployment manual 2 | 3 | This is the deployment manual for the Source Academy, to deploy your own clone of the Source Academy on a server that you control. For other options, see [educator resources](../educator/README.md). 4 | 5 | It is a work-in-progress, and is intended to: 6 | 7 | - be publically usable and available 8 | - describe a small range of deployment options 9 | - be more structured and versioned than the old single Google Doc 10 | 11 | We assume a reasonable level of familiarity with modern web infrastructure as 12 | well as Linux system administration. 13 | 14 | ## Quick start 15 | 16 | You should read the overview below first if you have not done so before. 17 | 18 | - [Frontend deployment](frontend/README.md) 19 | - [Backend deployment](backend/README.md) 20 | - [Auxilliary services deployment](auxilliary/README.md) 21 | - [Authentication services](auth/README.md) 22 | 23 | ## High-level overview 24 | 25 | The full Source Academy deployment as used for the CS1101S module in NUS SoC comprises these components: 26 | 27 | \* denotes a mandatory component\ 28 | \# denotes a component that can be shared (e.g. you could use our deployment of that component) 29 | 30 | ### Components developed in-house 31 | 32 | - [frontend](https://github.com/source-academy/frontend)*: the frontend. This is the part that users 33 | (students and staff) interact with. It is a standard React SPA written in TypeScript. One major dependency of the 34 | frontend is [js-slang](https://github.com/source-academy/js-slang), the implementation of our JavaScript subset 35 | language called Source. (It does not affect deployment, but it is good to know.) 36 | 37 | This can be deployed on any static site hosting service that supports SPAs (in particular, it must be able to rewrite 38 | non-existent paths to a 200 on index.html, as is needed for a SPA), such as Netlify, Vercel, Render, Surge, Cloudflare 39 | Pages, etc. GitHub Pages is not suitable as it does not allow you to rewrite non-existent paths. The CS1101S 40 | deployment uses Amazon CloudFront with Amazon S3. 41 | 42 | - [backend](https://github.com/source-academy/backend)*: the main backend, sometimes referred to as the Elixir backend. This 43 | stores most of the dynamic data: the users, assessments, students' work, grading, etc. It is built on the Phoenix 44 | framework, written in Elixir. 45 | 46 | This can be deployed on any Linux server. The CS1101S deployment uses an Amazon EC2 instance. 47 | 48 | - [grader](https://github.com/source-academy/grader): an AWS Lambda function that is called by the Elixir backend to 49 | autograde student submissions. Optional; without this, autograding of programming questions will not work. (MCQ 50 | questions are still autograded.) 51 | 52 | (It should not be too hard adapt the existing grader into an alternative, self-hosted solution for those who do not 53 | wish to use AWS. Contributions appreciated.) 54 | 55 | - [modules](https://github.com/source-academy/modules)#: a repository of libraries that can be `import`ed into programs. 56 | This only needs any web hosting service; the CS1101S deployment uses GitHub Pages. It is possible to simply use our 57 | module repository at https://source-academy.github.io/modules/. Optional; without this, modules will not be available. 58 | (While some libraries such as the runes, curves and sounds library are currently bundled with the frontend, they will 59 | eventually be migrated to be modules.) 60 | 61 | - [sharedb-ace-backend](https://github.com/source-academy/sharedb-ace-backend)#: a simple backend service that exposes a 62 | ShareDB database. This is used for the collaborative editor functionality. It is possible to simply use our instance; 63 | contact us for more information. Optional; without this, the collaborative editor will not be available. 64 | 65 | This can be deployed on any Linux server. The CS1101S deployment uses an Amazon EC2 instance. 66 | 67 | ### Off-the-shelf components 68 | 69 | - PostgreSQL*: the main database where the Elixir backend stores its data. You can run your own instance or use a 70 | managed instance. The CS1101S deployment uses Amazon RDS. 71 | 72 | - [YOURLS](https://github.com/YOURLS/YOURLS)#: the URL shortener service, used to provide the share function in the 73 | Playground. It is possible to simply use our instance; contact us for more information. Optional; without this, the 74 | share function in the Playground will not be available. 75 | 76 | This can be deployed on any service that supports PHP. It additionally requires a MariaDB (or MySQL) instance. The 77 | CS1101S deployment runs this using php-fpm, nginx and MariaDB on an EC2 instance. 78 | 79 | ### Cloud services 80 | 81 | - Amazon S3: used to store game assets and Sourcecast audio files. Optional; without this, it will not be possible to 82 | use the game editor, or Sourcecasts. The game itself can still run if its assets are hosted elsewhere (any web host 83 | will do), but because the game editor uses the S3 API to upload files, as does the Sourcecasts feature, those will not 84 | work. 85 | 86 | (It should not be too hard to allow these features to work without S3 e.g. just uploading the files to the backend 87 | itself and serving it from there. Any contributions will be appreciated.) 88 | 89 | - Amazon IoT: used as an MQTT broker for the remote execution functionality. Optional; without this, the remote 90 | execution functionality (i.e. robotics) will not work. 91 | 92 | (This only really needs modifications to the Elixir backend to support authenticating with a different, possibly 93 | self-hosted, MQTT broker. Again, any contributions will be appreciated.) 94 | 95 | - Authentication service*: used to authenticate users. Any service supporting OpenID or OAuth2 works, but some code 96 | modifications may be needed (to determine the user's role—whether they are a student or staff—from the 97 | token provided by the authentication provider). The CS1101S deployment uses the university's single sign-on service. 98 | There is also support for Amazon Cognito, which is used for the staging deployment. It is not hard to add support for 99 | other services provided that they support OAuth2 or OpenID. 100 | 101 | - Google Drive: used for the Google Drive integration. You only need to obtain an API key and OAuth credentials; the 102 | deployment guide will detail this. Optional; without this, the Google Drive integration will be unavailable. 103 | 104 | - [Sentry](https://sentry.io): used to capture errors on both the backend and frontend. Optional, of course; it is 105 | really useful only to us as the primary developers, but is included here for completeness' sake. 106 | 107 | ## Deployment costs 108 | 109 | A full deployment on AWS (except the modules repository) supporting over 600 students and about 80 instructors costs 110 | about 120 to 130 USD per month, give or take. Using AWS IoT may add another 30 USD per month, thereabouts, during the 111 | period it is used. 112 | 113 | This estimate includes about 50 USD per month in bandwidth costs. It may be slightly lower if you are in an AWS region 114 | with lower bandwidth costs (the Singapore ap-southeast-1 region has one of the highest). 115 | 116 | Most components are not tied to AWS, so it is possible to use cheaper (or free) services, or host on 117 | institution-provided servers. 118 | 119 | ## Get started 120 | 121 | Start off by deploying [the backend](backend/README.md), then [the frontend](frontend/README.md), followed by [the auxilliary services](auxilliary/README.md). 122 | 123 | If your organisation has no in-house authentication service, you may wish to follow one of the guides on [authentication services](auth/README.md) as well. 124 | -------------------------------------------------------------------------------- /deployment/auth/README.md: -------------------------------------------------------------------------------- 1 | # Authentication services 2 | 3 | * [In-house service](#in-house-service) 4 | * [Google](#google) 5 | * [Amazon Cognito](#amazon-cognito) 6 | * [Auth0](#auth0) 7 | 8 | ## In-house service 9 | 10 | If you wish to integrate with your organisation/institution's pre-existing authentication service, you will likely have 11 | to write a custom authentication provider yourself. 12 | 13 | In general, it should be simple to integrate any service that supports the OAuth2 authorisation code flow. You will then 14 | need to write an authentication provider that receives the authorisation code and then exchanges it for a authorisation 15 | token, and retrieves the user's username, name, and role via API calls or by extracting it from the token. 16 | 17 | See our [LumiNUS authentication 18 | provider](https://github.com/source-academy/backend/blob/master/lib/cadet/auth/providers/luminus.ex) for an example. 19 | 20 | If your authentication provider supports OpenID Connect and exposes an OpenID discovery document, then most of this is 21 | handled for you via the OpenID authentication provider; you will only need to write an extractor that, given the access 22 | token, returns the user's username, name, and role. See our [Cognito claim 23 | extractor](https://github.com/source-academy/backend/blob/master/lib/cadet/auth/providers/cognito_claim_extractor.ex) for 24 | an example. 25 | 26 | ## Google 27 | 28 | You can use Google as an authentication service. This means that users will sign in using their Google account. The 29 | Google account can be a normal @gmail.com account, or it can be an organisation/G Suite account. 30 | 31 | Note that because it is not possible to restrict who has a Google account, you must manually create users in the 32 | database if you are using Google as an authentication service. 33 | 34 | 1. Go to the [Google API Console](https://console.cloud.google.com/apis/dashboard), and create a project (or use one you 35 | already have, if you wish). 36 | 37 | 2. Go to the [credentials](https://console.cloud.google.com/apis/credentials) page. At the top, select Create 38 | credentials, then select the OAuth client ID option. Select Web application as the application type. Give it any 39 | name. 40 | 41 | Under Authorised redirect URIs, add the URI to the `/login?provider=google` route of your deployment. For example, if 42 | your deployment is accessible at `https://sourceacademy.nus.edu.sg`, add `https://sourceacademy.nus.edu.sg/login`. 43 | Note: if Google is not your first authentication provider in the frontend configuration, add `?provider=google` to 44 | the URI. 45 | 46 | You can also add localhost e.g. `http://localhost:8000/login` for the local frontend development 47 | server. 48 | 49 | 3. Go to the [OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) page and configure it to 50 | your liking. There are no special scopes required. 51 | 52 | 4. Note the client ID and client secret created in step 2. 53 | 54 | In your frontend configuration, add the following variables, changing the number and `CLIENT_ID_HERE` accordingly. Note: if the number is not 1, make sure you followed the note in step 2. 55 | 56 | ``` 57 | REACT_APP_OAUTH2_PROVIDER1=google 58 | REACT_APP_OAUTH2_PROVIDER1_NAME=Google 59 | REACT_APP_OAUTH2_PROVIDER1_ENDPOINT=https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=CLIENT_ID_HERE&scope=openid%20email 60 | ``` 61 | 62 | In your backend configuration (`cadet.exs`), add the following to the `identity_providers` map: 63 | 64 | ```elixir 65 | "google" => 66 | {Cadet.Auth.Providers.OpenID, 67 | %{ 68 | openid_provider: :google, 69 | claim_extractor: Cadet.Auth.Providers.GoogleClaimExtractor 70 | }}, 71 | ``` 72 | 73 | and the following to the `openid_connect_providers` list: 74 | 75 | ```elixir 76 | google: [ 77 | discovery_document_uri: "https://accounts.google.com/.well-known/openid-configuration", 78 | client_id: "CLIENT_ID_HERE", 79 | client_secret: "CLIENT_SECRET_HERE", 80 | response_type: "code", 81 | scope: "openid email" 82 | ], 83 | ``` 84 | 85 | 5. Done! Note that you need to [add users manually](../maint/add-users.md). For Google, the username is the primary 86 | email of the Google account. 87 | 88 | ## Amazon Cognito 89 | 90 | TODO. 91 | 92 | ## Auth0 93 | 94 | TODO. 95 | -------------------------------------------------------------------------------- /deployment/auxilliary/README.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | -------------------------------------------------------------------------------- /deployment/backend/README.md: -------------------------------------------------------------------------------- 1 | # Backend 2 | 3 | The backend can be deployed on any Linux server. (It is, in theory, possible to 4 | deploy it on Windows and macOS as well, as Elixir runs on those platforms, but 5 | we do not test that the backend works those platforms.) 6 | 7 | ## Deployment methods 8 | 9 | - Local development: see the [backend README](https://github.com/source-academy/backend#developer-setup) 10 | - [Install on Linux server](#install-on-linux-server) 11 | - [Full Terraform deployment](terraform.md) (This is what is used by CS1101S.) 12 | 13 | ## Scripted install on Linux server 14 | 15 | 1. On the server, [configure the backend](shared.md#configuring-the-backend). 16 | 17 | 2. If you are running on Ubuntu 20.04, you can run the automated installation script: 18 | 19 | ```bash 20 | curl -LO https://raw.githubusercontent.com/source-academy/backend/stable/deployment/init.sh 21 | # inspect init.sh 22 | sudo bash init.sh 23 | ``` 24 | 25 | The script downloads and extracts the precompiled Linux release, sets up a systemd unit file, and starts the backend. 26 | The configuration file should be at `/etc/cadet.exs`. 27 | 28 | If you are not running Ubuntu 20.04, you may try the script, but the precompiled script may not work if your glibc 29 | version is not new enough. In that case, [manually compile](#manual-compile) the backend and install it. 30 | 31 | 3. Check that the backend is accessible at http://localhost:4000 (on the server). 32 | 33 | 4. Note that you need a service to act as a TLS termination proxy for the backend. If you are following our Terraform 34 | deployment, this will be AWS's Elastic Load Balancer. 35 | 36 | If not, consider using Nginx. [This 37 | guide](https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-load-balancing-with-ssl-termination) may 38 | be helpful, but instead of having an upstream with multiple endpoints, just `proxy_pass http://localhost:4000`. 39 | 40 | Alternatively, you can terminate SSL directly at the backend; follow [this 41 | guide](https://hexdocs.pm/phoenix/using_ssl.html) (the configuration changes can be merged into the endpoint key in 42 | `cadet.exs`). 43 | 44 | 5. Check that the backend is accessible over HTTPS from your own computer. 45 | 46 | 6. Next, follow the guide to [manually setup the optional AWS services](aws-manual.md), if needed. 47 | 48 | To update the backend, repeat steps 2, 3, 4, and 6. 49 | 50 | ## Manual compile 51 | 52 | 1. [Compile the backend](shared.md#compiling-the-backend). 53 | 54 | 2. Transfer the package to the server the backend will be run on. 55 | 56 | 3. On the server, [configure the backend](shared.md#configuring-the-backend). 57 | 58 | 4. Install this systemd unit file onto the server, at `/etc/systemd/system/cadet.service`. 59 | 60 | ```ini 61 | [Unit] 62 | After=network.target 63 | Requires=network.target 64 | StartLimitIntervalSec=0 65 | 66 | [Service] 67 | Type=simple 68 | TimeoutStartSec=0 69 | Restart=always 70 | RestartSec=5 71 | ExecStart=/opt/cadet/bin/cadet start 72 | User=nobody 73 | Environment=HOME=/opt/cadet/tmp 74 | Environment=PORT=4000 75 | 76 | [Install] 77 | WantedBy=multi-user.target 78 | ``` 79 | 80 | 5. Place this Bash script into the same directory as the package. 81 | 82 | ```bash 83 | #!/bin/bash 84 | 85 | BASEDIR=/opt/cadet 86 | 87 | sudo systemctl stop cadet 88 | sudo rm -rf "$BASEDIR" 89 | sudo mkdir -p "$BASEDIR" 90 | sudo tar -zxf cadet-0.0.1.tar.gz -C "$BASEDIR" --no-same-owner 91 | sudo mkdir -p "$BASEDIR/tmp" 92 | sudo chmod 1777 "$BASEDIR"/{tmp,lib/tzdata-*/priv/tmp_downloads} 93 | sudo chmod a+x "$BASEDIR"/{bin/cadet,erts-*/bin/*,releases/*/{iex,elixir}} 94 | sudo chown -R nobody:nogroup "$BASEDIR"/lib/tzdata-*/priv/{release_ets,latest_remote_poll.txt} 95 | sudo systemctl start cadet 96 | # this just loops until we can reach the running application 97 | while ! "$BASEDIR/bin/cadet" rpc 1; do 98 | sleep 0.5 99 | done 100 | sleep 5 # Allow application to fully start up - avoid a race condition 101 | "$BASEDIR/bin/cadet" rpc Cadet.Release.migrate 102 | ``` 103 | 104 | (Note: adapt as needed. This script makes it so the extracted files are owned by root, but gives write access to 105 | certain files which are modified at runtime. It assumes that the backend is going to be run as `nobody`.) 106 | 107 | Make it executable and execute the script. 108 | 109 | The script extracts the release package to `/opt/cadet`. If you wish to install it somewhere else, change the script 110 | and systemd service file accordingly. 111 | 112 | 6. Continue with the rest of the steps in the scripted install guide. 113 | -------------------------------------------------------------------------------- /deployment/backend/aws-manual.md: -------------------------------------------------------------------------------- 1 | # Setting up AWS services manually 2 | 3 | TODO. 4 | 5 | - S3 6 | - Lambda 7 | - IoT 8 | -------------------------------------------------------------------------------- /deployment/backend/shared.md: -------------------------------------------------------------------------------- 1 | # Compiling the backend 2 | 3 | You should do this on a system similar to the system you will be using the backend on i.e. use same Linux distribution. 4 | Compiling on a different Linux distribution should work as long as the Elixir you use to compile does not depend on 5 | too-new a glibc. (Of course, you can just do this on the server you will be running the backend on.) 6 | 7 | 1. Install Elixir on your system. Make sure the versions are at least those listed 8 | [here](https://github.com/source-academy/backend#system-requirements). Following the instructions 9 | [here](https://elixir-lang.org/install.html) is fine. If you want to use a version manager like 10 | [asdf](https://github.com/asdf-vm/asdf), that should be fine too. (But we do the former.) 11 | 12 | After installing Elixir, set up the dependency manager: `mix local.hex --force && mix local.rebar --force` 13 | 14 | 2. Clone the cadet repository: `git clone https://github.com/source-academy/backend.git` 15 | 16 | 3. Enter the directory and install dependencies: `MIX_ENV=prod mix deps.get` 17 | 18 | 4. Build: `MIX_ENV=prod mix release` 19 | 20 | 5. The release archive is at `_build/prod/cadet-0.0.1.tar.gz`. 21 | 22 | 6. Return to the guide you came from. 23 | 24 | # Configuring the backend 25 | 26 | The backend in production mode loads its configuration from `/etc/cadet.exs` by default. You can specify a path in the 27 | environment variable `CONFIG` to override this. 28 | 29 | Copy the [example configuration](https://github.com/source-academy/backend/blob/master/config/cadet.exs.example) to 30 | `/etc/cadet.exs` (or some other location, if you are overriding the default), and edit the values. If you are following 31 | the Terraform deployment, you will upload the file to your configuration bucket instead. 32 | 33 | In particular, you should edit the CORS allowed origins (`cors_endpoints`), the database credentials, as well as all the 34 | AWS resource names and ARNs to match those you have created, if any. Also set up the authentication configuration; you 35 | may wish to check out the [authentication guide](../auth/README.md). 36 | 37 | If you are following the Terraform deployment, you can search and replace `` in the example 38 | configuration which should give you the correct name for all the AWS resources. 39 | 40 | Once done, return to the guide you came from. 41 | -------------------------------------------------------------------------------- /deployment/backend/terraform.md: -------------------------------------------------------------------------------- 1 | # Full Terraform deployment 2 | 3 | 1. [Install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli#install-terraform). 4 | 5 | Generate an AWS access key and secret for Terraform, and specify them [either as environment variables or using the 6 | AWS CLI configuration file](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#environment-variables). 7 | 8 | The access key must be able to access AWS IAM, Secrets Manager, RDS, S3, Lambda, STS, EC2, ELB, Autoscaling, and IoT. 9 | This policy works: 10 | 11 | ```json 12 | { 13 | "Version": "2012-10-17", 14 | "Statement": [ 15 | { 16 | "Sid": "VisualEditor0", 17 | "Effect": "Allow", 18 | "Action": [ 19 | "iam:*", 20 | "secretsmanager:*", 21 | "rds:*", 22 | "s3:*", 23 | "lambda:*", 24 | "sts:*", 25 | "ec2:*", 26 | "elasticloadbalancing:*", 27 | "autoscaling:*", 28 | "iot:*" 29 | ], 30 | "Resource": "*" 31 | } 32 | ] 33 | } 34 | ``` 35 | 36 | 2. Generate an SSH RSA key locally using `ssh-keygen`, and upload the public key to AWS EC2. We will refer to this as 37 | the "API SSH key". Also, upload your own SSH public key (which must be RSA since EC2 does not support Ed25519 38 | keys...) to EC2. We will refer to this as the "Bastion SSH key". 39 | 40 | The API SSH key is used to SSH from the Bastion node to the API nodes. The Bastion SSH key is used to SSH to the 41 | Bastion. 42 | 43 | Note: when uploading the public keys, be sure to switch to the correct AWS region! 44 | 45 | 3. In AWS Lambda, install the XVFB Lambda layer, and name it "xvfb". Also, download the compiled grader Lambda ZIP archive. 46 | 47 | (If you are not in the Source Academy organisation, please contact us for these archives. These are built on GitHub 48 | CI, but we are yet to publish these build artifacts in a way accessible to the public.) 49 | 50 | 4. Think of a unique identifier for your deployment. It will be used to name S3 buckets, so it needs to be something 51 | that is likely to be unique e.g. your module/course code, or some random identifier. (It must be alphanumeric, since 52 | it is used in S3 bucket names.) 53 | 54 | The identifier will be referred to using `` below. 55 | 56 | 5. Create the assets bucket, which contains game/story assets. If you already have an assets bucket from a previous 57 | deployment, you can use that. 58 | 59 | Go to AWS S3, and select Create bucket. Name it `-assets`, and select the correct AWS region. 60 | 61 | Uncheck Block all public access, and tick the acknowledgement. The remaining settings can be left at their default. 62 | 63 | Once the bucket is created, open the bucket and go to the Permissions tab. In the Bucket policy panel, select Edit. 64 | Paste the following, filling in ``: 65 | 66 | ```json 67 | { 68 | "Version": "2012-10-17", 69 | "Statement": [ 70 | { 71 | "Sid": "AddPerm", 72 | "Effect": "Allow", 73 | "Principal": "*", 74 | "Action": "s3:GetObject", 75 | "Resource": "arn:aws:s3:::-assets/*" 76 | } 77 | ] 78 | } 79 | ``` 80 | 81 | This bucket policy makes all objects accessible, which is required as this bucket serves game/story assets. 82 | 83 | 6. Create the configuration bucket, which contains the backend configuration. If you already have a configuration bucket from a previous deployment, you can use that. 84 | 85 | Go to AWS S3, and select Create bucket. Name it `-config`, and select the correct AWS region. 86 | 87 | **Select** Block all public access. The remaining settings can be left at their default. 88 | 89 | 7. [Configure the backend](shared.md#configuring-the-backend). Then upload the file to the configuration bucket created 90 | in the last step. (You can name the file anything; you might use `cadet.exs`, for example.) 91 | 92 | 8. Enter the `deployment/terraform` directory of your copy of the backend repository. 93 | 94 | Create a file `terraform.tfvars` in the directory, with these contents: 95 | 96 | ``` 97 | api_ssh_key_name = "API SSH key name here (as named in EC2)" 98 | bastion_ssh_key_name = "Bastion SSH key name here (as named in EC2)" 99 | lambda_filename = "path/to/grader.zip (on your local machine)" 100 | env = "" 101 | assets_bucket = "-assets (as in step 4)" 102 | config_bucket = "-config (as in step 5)" 103 | config_object = "cadet.exs (as in step 5)" 104 | ``` 105 | 106 | Fill in the fields. You can also specify the values of other parameters. See `inputs.tf`. 107 | 108 | 9. Open `main.tf`. 109 | 110 | Modify the details under the "backend" key as needed. The defaults specify the S3 bucket used by the CS1101S 111 | deployment. You can also use [other backends](https://www.terraform.io/docs/language/settings/backends/index.html). 112 | 113 | Note: "backend" in Terraform parlance refers to the location Terraform persists its state. 114 | 115 | Modify the details under the "provider" key as needed. (Mainly the AWS region.) 116 | 117 | 10. Initialise Terraform by running `terraform init` (in the current directory i.e. `backend/deployment/terraform`). 118 | 119 | 11. Provision the resources by running `terraform apply`. 120 | 121 | Note: if you are running on Mac, ensure that you have granted your Terminal and/or whatever application you are 122 | running Terraform through (e.g. VS Code using its built-in terminal) has the Full Disk Access permission. 123 | 124 | Note: if you encounter an error like this: 125 | 126 | > error creating Secrets Manager Secret: InvalidRequestException: You can't create this secret because a secret with 127 | > this name is already scheduled for deletion 128 | 129 | you will have to use the AWS CLI to force-delete the secret: 130 | 131 | ``` 132 | aws secretsmanager delete-secret --force-delete-without-recovery --secret-id secret-id-here 133 | ``` 134 | 135 | 12. In AWS IoT, create a Thing Group and name it `-sling`, if a thing group by that name does not 136 | already exist. Go to the Security tab and attach the `-sling` policy to it. 137 | 138 | (This is done because Terraform's AWS provider does not yet support thing groups.) 139 | 140 | 13. Go to CloudFront. Create or update the distribution for the backend. 141 | 142 | If you already have a distribution configured for the backend in the past, simply update the origin to the ELB that 143 | was just created. 144 | 145 | If not, create a new CloudFront distribution. Select the ELB created in step 8 as the origin. 146 | 147 | Leave the rest of the origin settings as default. In particular: 148 | 149 | - Origin protocol policy: HTTP only 150 | - HTTP port: 80 151 | 152 | For the default cache behaviour: 153 | 154 | - Viewer protocol policy: HTTPS only 155 | - Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE 156 | - Cached HTTP methods: Tick OPTIONS 157 | - Select Use legacy cache settings 158 | - Cache based on selected request headers: Whitelist 159 | - Add Authorization and Host 160 | - Query string forwarding and caching: Forward all, cache based on all 161 | - Compress objects automatically: Yes 162 | 163 | Any other options can be left at the default. 164 | 165 | 14. Wait for the distribution to propagate. Then, test that the backend can be reached. 166 | 167 | 15. Done! 168 | -------------------------------------------------------------------------------- /deployment/frontend/README.md: -------------------------------------------------------------------------------- 1 | # Frontend deployment 2 | 3 | The frontend can be deployed on any static site hosting service that supports SPAs. 4 | 5 | ## Deployment methods 6 | 7 | - Local development: see the [frontend 8 | README](https://github.com/source-academy/frontend#installation-of-course-edition). 9 | - [Manual build and deploy to a web server](#manual-deployment) 10 | - [Deployment to a static site host](#static-site-host-deployment) 11 | - [Amazon S3 + CloudFront deployment](aws.md) (This is what is used by CS1101S.) 12 | 13 | ## Manual deployment 14 | 15 | 1. Clone the frontend repository: `git clone https://github.com/source-academy/frontend.git` 16 | 17 | 2. Enter the directory and install dependencies: `yarn install --frozen-lockfile` 18 | 19 | 3. Configure the frontend for your deployment. [See the frontend 20 | README](https://github.com/source-academy/frontend#setting-up-your-environment), as well as the [production-specific 21 | configuration](https://github.com/source-academy/frontend#build-and-deployment). Also set up the authentication 22 | configuration; you may wish to check out the [authentication guide](../auth/README.md). 23 | 24 | Additionally set (in the `.env` file) `PUBLIC_URL` to be the URL of your deployment. For example, 25 | `https://sourceacademy.org`. If you are not deploying to the root of the domain, you must specify the full 26 | path as well. (Note that deploying to a subdirectory is untested and may not work.) 27 | 28 | 4. Run the build: `yarn run build` 29 | 30 | 5. The build is output to `build/`. Upload the files to your web host. 31 | 32 | 6. Ensure that your web host is configured to route all non-existent paths to the root (i.e. `/` or `/index.html`). This 33 | might be done through a `.htaccess` file if your host uses the Apache httpd. 34 | 35 | 7. Done! 36 | 37 | To update the site, simply repeat steps 4 onwards after pulling and/or making your desired changes. 38 | 39 | ## Static site host deployment 40 | 41 | The stack used by the frontend is very common and quite well-supported. Some services include 42 | [Netlify](https://www.netlify.com/), [Vercel](https://vercel.com/), [Render](https://render.com/), 43 | [Surge](https://surge.sh/), and [Cloudflare Pages](https://pages.cloudflare.com/). 44 | 45 | Most of these services are able to integrate with a GitHub repository and deploy automatically on push. 46 | 47 | 1. First, [fork the repository](https://github.com/source-academy/frontend). 48 | 49 | 2. Create a new site in your preferred service, and select your forked repository. 50 | 51 | 3. Set the build command to `yarn run build`, and the build output directory to `build/`. If needed, specify the command 52 | to install dependencies as `yarn install --frozen-lockfile`. Consult your service's documentation on deploying Yarn 53 | (or Node.js) projects for more information. 54 | 55 | 4. Configure the frontend. Instead of using a `.env`, you should be able to set environment variables using the 56 | service's interface or configuration file. 57 | 58 | [See the frontend README](https://github.com/source-academy/frontend#setting-up-your-environment), as well as the 59 | [production-specific configuration](https://github.com/source-academy/frontend#build-and-deployment), for the 60 | environment variables to configure. 61 | 62 | Additionally set `PUBLIC_URL` to be the URL of your deployment. For example, `https://sourceacademy.org`. 63 | 64 | 5. Trigger a build using the service. 65 | 66 | 6. Ensure that your web host is configured to route all non-existent paths to the root (i.e. `/` or `/index.html`). 67 | Consult your service's documentation on deploying single-page apps (SPAs) for more information. (Note: GitHub Pages 68 | does not support this.) 69 | 70 | 7. Done! 71 | 72 | To update the site, you should be able to push directly to your fork. 73 | -------------------------------------------------------------------------------- /deployment/frontend/aws.md: -------------------------------------------------------------------------------- 1 | # Frontend Amazon S3 + CloudFront deployment 2 | 3 | If you are using an AWS IAM user instead of the root user to access your account, ensure you have access to S3 and 4 | CloudFront. 5 | 6 | 1. If you have not already done so, [install the AWS 7 | CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html). Then, [generate an access key for your 8 | user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey) and 9 | [configure the AWS 10 | CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config) 11 | with those credentials. 12 | 13 | For the default AWS region, you should [pick the AWS 14 | region](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions) 15 | closest to you and your users. Use this region for all AWS services that you use. 16 | 17 | 2. Follow AWS's tutorial on [creating an S3 bucket for static website 18 | hosting](https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html). 19 | 20 | **Do only steps 1 to 4** ("Create a bucket", "Enable static website hosting", "Edit Block Public Access settings", 21 | and "Add a bucket policy that makes your bucket content publicly available"). 22 | 23 | In step two, fill in `index.html` for both the index and error document. 24 | 25 | Do not upload files yet. 26 | 27 | 3. Follow steps 1 to 4 of the [manual deployment guide](./README.md#manual-deployment) to configure and build the frontend. 28 | 29 | Then, in your shell, enter the `build` directory and run the following commands to upload the files to the bucket. 30 | 31 | ``` 32 | aws s3 sync --delete --exclude '*.wasm' . "YOUR BUCKET NAME HERE" 33 | aws s3 sync --exclude '*' --include '*.wasm' --content-type 'application/wasm' . "YOUR BUCKET NAME HERE" 34 | ``` 35 | 36 | Replace `YOUR BUCKET NAME HERE` with the name of your bucket. 37 | 38 | 4. Follow AWS's tutorial on [using CloudFront to serve a static website hosted on 39 | S3](https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-serve-static-website/#Using_a_website_endpoint_as_the_origin.2C_with_anonymous_.28public.29_access_allowed). 40 | 41 | You have already done steps 1 and 3 in that tutorial in step 2 of this guide. 42 | 43 | When creating the CloudFront distribution, under "Default Cache Behavior Settings", select "Yes" for "Compress 44 | Objects Automatically". 45 | 46 | 5. Done! 47 | 48 | To update the site, simply repeat step 3 of this guide. Additionally, run the following command: 49 | 50 | ``` 51 | aws cloudfront create-invalidation --distribution-id "CLOUDFRONT ID HERE" --paths '/externalLibs/*' '/manifest.json' '/asset-manifest.json' '/service-worker.js' '/index.html' '/assets/*' '/' 52 | ``` 53 | 54 | Replace `CLOUDFRONT ID HERE` with your distribution ID (something like `EA3DF4YZDML1G`). 55 | 56 | This command creates an _invalidation_, clearing the CloudFront cache so updated contents are served. 57 | 58 | You can also do this via the AWS console under the "Invalidations" tab of the distribution. If so, these are the paths to invalidate: 59 | 60 | ``` 61 | /externalLibs/* 62 | /manifest.json 63 | /asset-manifest.json 64 | /service-worker.js 65 | /index.html 66 | /assets/* 67 | / 68 | ``` 69 | -------------------------------------------------------------------------------- /deployment/maint/add-users.md: -------------------------------------------------------------------------------- 1 | # Adding users 2 | 3 | ## Using a CSV 4 | 5 | Note that this method is mainly for bulk-importing student and staff users. This will let you assign group leaders as well. 6 | 7 | 1. Prepare the following CSVs, without headers and with the fields name, username, group name, in that order. All fields are required. 8 | 9 | 1. students 10 | 2. group leaders (TAs) 11 | 3. mentors 12 | 13 | You only need to create the CSVs that you wish to update. 14 | 15 | Users are keyed by username, and groups are keyed by group name. If there are multiple rows with the same key, the later rows will overwrite the earlier rows. 16 | 17 | Leaders and mentors are created with the staff role. They are set as the leader (or mentor) of the specified group, but they are not themselves added to the group. 18 | 19 | Note: groups are used only to group students into their tutorial groups. The group leader is meant to be the group's TA, and the leader's grading view will be by default filtered to show only their group's submissions. The group mentor field is currently unused. 20 | 21 | 2. Transfer the CSVs to the server the backend is running on. Note: if you are using our Terraform deployment with 2 (or 22 | more) redundant nodes, you only need to transfer the CSVs (and do the remaining steps) on one of the nodes. 23 | 24 | 3. Enter the Elixir REPL in the context of the backend. If you followed the deployment guides, you can run `/opt/cadet/bin/cadet remote` to do so. 25 | 26 | 4. Execute `Mix.Tasks.Cadet.Users.Import.run(nil)` 27 | 28 | 5. Enter the paths to the files as needed. 29 | 30 | 6. Done! 31 | 32 | ## Directly via SQL 33 | 34 | 1. Connect to your PostgreSQL database using `psql` or whatever preferred tool you use. 35 | 36 | 2. Add users: 37 | 38 | ```sql 39 | INSERT INTO users (name, role, username, inserted_at, updated_at) values ('name', 'admin', 'username', NOW(), NOW()); 40 | ``` 41 | 42 | 3. Done! 43 | -------------------------------------------------------------------------------- /developer/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | label: Developers 3 | --- 4 | 5 | # Resources for developers 6 | 7 | ## Community 8 | 9 | The Source Academy was conceived, designed, and implemented by a community of undergraduate students. See the [contributors page](https://sourceacademy.org/contributors) for the Hall of Fame, current project leadership, and all Github contributors. 10 | 11 | ## Current Development Activities 12 | 13 | Currently (2023-2024) the following intiatives are under way to extend and improve 14 | Source Academy. All of these are being pursued by Computer Science undergraduate 15 | students of the National University of Singapore. 16 | 17 | - Numerous improvements in the frontend and backend, including game support, grading, folders, visualization, share links, sessions, stories, contests, and mobile support 18 | - Support for new languages: TypeScript, Scheme, Python, C, Java, C# 19 | 20 | ## Deployment 21 | 22 | - The serverless frontend (GitHub repo `frontend`) is currently auto-deployed to [sourceacademy.org](https://sourceacademy.org). 23 | - The JavaScript language implementations (GitHub repo `js-slang`) are (manually) published to [NPM js-slang](https://www.npmjs.com/package/js-slang). The NPM package `js-slang` is imported by the frontend. The implementations of 24 | - Python (GitHub repo `py-slang`) and 25 | - Scheme (GitHub repo `scm-slang`) 26 | 27 | are sub-modules of `js-slang`; they consist of frontends to `js-slang`. 28 | - The C language implementations (GitHub repo `c-slang`) are (manually) published to [NPM @sourceacademy/c-slang](https://www.npmjs.com/package/@sourceacademy/c-slang). The NPM package `@sourceacademy/c-slang` is imported by the frontend. 29 | - The Java language implementations (GitHub repo `java-slang`) are (manually) published to [NPM java-slang](https://www.npmjs.com/package/@sourceacademy/java-slang). The NPM package `@sourceacademy/java-slang` is imported by the frontend. 30 | - The WebAssembly-based language implementation (GitHub repo `sourceror`) is (manually) published to [NPM sourceror](https://www.npmjs.com/package/sourceror). 31 | - The sharing service for collaborative editing (GitHub repo `sharedb-ace`) is (manually) published to [NPM @sourceacademy/sharedb-ace](https://www.npmjs.com/package/@sourceacademy/sharedb-ace). 32 | - The runtime component for Source on embedded systems (GitHub repo `sling`) is (manually) published to [NPM @sourceacademy/sling-client](https://www.npmjs.com/package/@sourceacademy/sling-client). 33 | - The JavaScript module that goes with [SICP JS](https://sourceacademy.org/sicpjs/index) (GitHub repo `sicp`) is auto-deployed to [NPM sicp](https://www.npmjs.com/package/sicp) 34 | - The [SICP JS](https://sourceacademy.org/sicpjs/index) textbook chapters, sections, and subsections (GitHub repo `sicp`) are auto-deployed to `sicp.sourceacademy.org/json`, e.g. [sicp.sourceacademy.org/json/1.json](https://sicp.sourceacademy.org/json/1.json). 35 | - SourceAcademy @ NUS (including the backend, GitHub repo `backend`) is (manually) deployed to an AWS server at [sourceacademy.nus.edu.sg](https://sourceacademy.nus.edu.sg). 36 | - The Source Academy modules (GitHub repo `modules`) are auto-deployed to [source-academy.github.io/modules](https://source-academy.github.io/modules/documentation/) via Github Pages. The following NPM packages are managed by the Source Academy team and imported in `modules`: 37 | - The package `source-academy-wabt` (GitHub repo `wabt`) is manually deployed to [source-academy-wab](https://www.npmjs.com/package/source-academy-wabt). 38 | - The package `saar` (GitHub repo `saar`) is manually deployed to [saar](https://www.npmjs.com/package/saar). 39 | - The package `nbody` (GitHub repo `nbody`) is manually deployed to [nbody](https://www.npmjs.com/package/nbody). 40 | - This site (GitHub repo `general`) is auto-deployed to [about.sourceacademy.org](https://about.sourceacademy.org) via GitHub Pages. 41 | 42 | ## Get Involved 43 | 44 | To get involved, feel free to propose fixes, improvements, or projects using the Issues feature in the [Source Academy repos](https://github.com/source-academy) or send an email to [source.academy.nus@gmail.com](mailto:source.academy.nus@gmail.com). 45 | 46 | You can also follow [Source Academy on LinkedIn](https://www.linkedin.com/company/source-academy). 47 | -------------------------------------------------------------------------------- /educator/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | label: Educators 3 | --- 4 | 5 | # Resources for educators 6 | 7 | The educators in the Source Academy community might find the following resources useful. In addition, the NUS instructor team provides educator material including homework assignments, exams of previous years with solutions, and weekly classroom exercises. Email [sourceacademy@nus.edu.sg](mailto:sourceacademy@comp.nus.edu.sg) to get access to these resources. 8 | 9 | Educators have the following options to work with [SICP JS](https://sourceacademy.org/sicpjs/): 10 | - Not use Source Academy: You can use SICP JS with the IDE of your choice; [see here](../package/README.md) for more information 11 | - Use the public version of the Source Academy; [see here](../vanilla/README.md) how [Source Academy](https://sourceacademy.org/) supports your course 12 | - Source Academy @ NUS: An extension of Source Academy; [go here](https://sourceacademy.nus.edu.sg) to create your account and start your course 13 | - Deploy your own Source Academy @ X; [see here](../deployment/README.md) how to do that 14 | 15 | Educators who have used the original Scheme-based SICP book may appreciate our [Scheme-JavaScript Comparison Edition](https://sicp.sourceacademy.org), where SICP and SICP JS can be viewed side-by-side. 16 | 17 | ## Learner resources 18 | 19 | See [Resources for learners](../learner/README.md) 20 | 21 | ## Resources for educators who use [Source Academy @ NUS](https://sourceacademy.nus.edu.sg/) 22 | 23 | - Register as instructor: send an email to [source.academy.nus@gmail.com](mailto:source.academy.nus@gmail.com) 24 | - [Guide for authoring and uploading assessments](assessment/README.md): homework submissions stored on the **Source Academy @ NUS** or any other Source Academy server, graded by you and your assistants or auto-graded 25 | - [Guide for managing contest voting](voting/README.md): setup for students to vote for the most popular submissions in a contest 26 | - [Guide for setting up a Source Academy game](game/README.md): game provides context for homework assignments 27 | 28 | ## Courses using SICP JS and Source Academy 29 | 30 | - [CS1101S at NUS](https://www.comp.nus.edu.sg/~cs1101s): CS1 course for Computer Science majors at National University of Singapore, using SICP JS since 2012 31 | - [A Taste of Programming with SICP JS](https://about.sourceacademy.org/IAP/): MIT course during Independent Activity Period, January 18-28, 2022 32 | - [Program construction and data structures](https://www.uu.se/utbildning/kursplan?query=47706): CS1 course for Computer Science majors at Uppsala University in Sweden, using SICP JS since 2022 33 | 34 | -------------------------------------------------------------------------------- /educator/assessment/README.md: -------------------------------------------------------------------------------- 1 | ## Guide for Assessment Configuration 2 | 3 | ### Bonus XP calculation 4 | 5 | The follwing diagram explains the two configurable numbers(`max bonus xp` and `early hours before xp decay`) in our system for calculating the bonus xp for assessments. 6 | 7 | ![bonus_xp](https://user-images.githubusercontent.com/39845424/125188426-537a5600-e266-11eb-972f-7113a2d31201.png) 8 | 9 | ## Guide for authoring and uploading assessments 10 | 11 | Pieces of work that are to be submitted by students and the can be graded are called _assessments_ in the Source Academy. 12 | 13 | Instructors can specify assessments in an XML format that is documented in this page. They upload assessment files using the "Ground Control" feature of the Source Academy frontend. 14 | 15 | Your Source Academy deployment comes with an authoring tool for assessments. Visit 16 | https://your-source-academy-url/mission-control 17 | to access the tool. This page describes the XML format, in case you want to or need to manually edit the assessment XML files. 18 | 19 | ## General XML file format 20 | 21 | Each node may have `attributes`. Each node has either `children` nodes or a `value`. There are no empty elements. 22 | 23 | If a property is not documented for an element, then that element does not specify that property. For example, a [TASK](#task) has `attributes` and `children` nodes, and no `value`; and a [READING](#reading) has a `value` and neither `attributes` nor `children`. 24 | 25 | Each element is marked as `required` or `optional`. A `required` element is compulsory only if its parent element exists. **All attributes are required (i.e. compulsory) unless explicitly stated "optional"**. 26 | 27 | You may assume that each element must be unique (i.e. only one exists per parent), unless specified as "can have many". 28 | 29 | ## XML details 30 | 31 | - [TASK](#task) 32 | - [PASSWORD](#password) 33 | - [READING](#reading) 34 | - [WEBSUMMARY](#websummary) 35 | - [TEXT](#text) 36 | - [PROBLEMS](#problems) 37 | - [PROBLEM](#problem) 38 | - [programming](#programming) 39 | - [TEXT](#text) 40 | - [SNIPPET](#snippet) 41 | - [PREPEND](#prepend) 42 | - [TEMPLATE](#template) 43 | - [POSTPEND](#postpend) 44 | - [TESTCASES](#testcases) 45 | - [PUBLIC](#public) 46 | - [OPAQUE](#opaque) 47 | - [SECRET](#secret) 48 | - [SOLUTION](#solution) 49 | - [mcq](#mcq) 50 | - [TEXT](#text) 51 | - [CHOICE](#choice) 52 | - [voting](#voting) 53 | - [TEXT](#text) 54 | - [VOTING](#voting) 55 | - [SNIPPET](#snippet) 56 | - [PREPEND](#prepend) 57 | - [TEMPLATE](#template) 58 | 59 | - [DEPLOYMENT](#deployment) / [GRADERDEPLOYMENT](#graderdeployment) 60 | - [IMPORT](#import) 61 | - [SYMBOL](#symbol) 62 | - [EXTERNAL](#external) 63 | - [SYMBOL](#symbol) 64 | - [GLOBAL](#global) 65 | - [IDENTIFIER](#identifier) 66 | - [VALUE](#value) 67 | - [EXAMPLE ASSESSMENTS XML](#example-assessments-xml) 68 | 69 | ## TASK 70 | 71 | Represents an assessment. **Required**. 72 | 73 | ### Attributes 74 | 75 | | attribute | details | 76 | | ---------- | ------------------------------------------------------------------------------------------------------------------------ | 77 | | coverimage | The thumbnail to show for this assessment. Must be a URL, i.e. not a file path. e.g. "https://http.cat/200". Optional. | 78 | | number | The string identifier the relative position of this assessment. Must be unique among assessments. | 79 | | title | The title of this assessment. | 80 | | story | The story XML to load. Must correspond to the filename of a story XML file, e.g. "mission-2", "sidequest-2.1". Optional. | 81 | | access | Access control for the assessment. Can eitherbe set to "public" or "private". Defaults to "public". | 82 | 83 | With AY2018/19, there is a change in the way that assessments are named and ordered. E.g. from "mission-2", "mission-19", "sidequest-10.3" to "M2A", "Q10A". This change is reflected in the number attribute. 84 | 85 | The story XML to load in the game used to refer to this number attribute However, since the story XML filenames have not been updated to reflect this change in number, we need a new attribute story to point to the right story XML files. 86 | 87 | This is not necessarily a bad change, since a module staff may now explicitly refer to a story XML file to be loaded for the assessment, rather than have it be implicitly inferred from the number attribute. Additionally, module staff writing story XML files will now have greater flexibility in how to name their files. 88 | 89 | ### Children 90 | 91 | [READING](#reading), [WEBSUMMARY](#websummary), [TEXT](#text), [PROBLEMS](#problems), [DEPLOYMENT](#deployment), [GRADERDEPLOYMENT](#graderdeployment), [PASSWORD](#password) 92 | 93 | Example 94 | 95 | ```xml 96 | 103 | ... 104 | 105 | ``` 106 | 107 | ## PASSWORD 108 | 109 | Only appiles to "private" assessments. Please choose a strong a complex password. If no password is given, an empty string (`""`) will be used. 110 | 111 | ### Value 112 | 113 | A String that represents the assessment password. 114 | 115 | ### Example 116 | 117 | ```xml 118 | MySuperSecretPassword1!23%$#@% 119 | ``` 120 | 121 | ## READING 122 | 123 | Represents a recommended reading from the textbook. Optional. 124 | 125 | ### Value 126 | 127 | Text to be shown to the student, representing a recommended reading from the textbook. 128 | 129 | ### Example 130 | 131 | ```xml 132 | Textbook Sections 1.1.1 to 1.1.4 133 | ``` 134 | 135 | ## WEBSUMMARY 136 | 137 | Represents a summary of the assessment to be shown in the list of assessments. Relevant only for the cadet website. Optional. 138 | 139 | WEBSUMMARY is a new element defined for the cadet website. It is currently optional in order to minimise the amount of work required to migrate to this new API specification, but it is highly recommended that every [TASK](#task) have a WEBSUMMARY. 140 | 141 | ### Value 142 | 143 | Text to be shown to the student, representing a summary of the assessment. 144 | 145 | ### Example 146 | 147 | ```xml 148 | A small scare broke out in the server room of the spaceship... 149 | ``` 150 | 151 | ## TEXT 152 | 153 | Represents text to be shown to the student. Uses github-flavoured markdown. Can have many. 154 | 155 | Required: at least one TEXT element as a direct child of each TASK, PROBLEM, and CHOICE. 156 | 157 | ### Value 158 | 159 | Text to be shown to the student. The TEXT element may render differently based on its position and order in the XML tree. 160 | 161 | - As a child of [TASK](#task), the first TEXT element is taken to be the assessment briefing. This provides a general overview of the assessment. 162 | - As a child of [PROBLEM](#problem), the first TEXT element is taken to be the task description for "programming" questions, otherwise the MCQ question for "mcq" questions. 163 | - As a child of [CHOICE](#choice), the first TEXT element is taken to be the content of said choice in the PROBLEM. 164 | Other TASK elements may be rendered in the assessment pdf, but are otherwise ignored by cadet. 165 | 166 | Note that XML preserves whitespaces, so the indentations of the string in this value property will be exactly what is passed to the markdown parser; i.e. the text you write here should start with an absolute indentation level of 0. In addition, you must escape predefined XML entities quot ("), amp (&), apos ('), lt (<), and gt (>). 167 | 168 | Note that the current backend implementation supports only absolute URLs for embedded images, i.e. not file paths. You can consider using an online image hosting service, e.g. Imgur. 169 | 170 | ### Example 171 | 172 | ````xml 173 | 174 | Write a function `steps` that takes four runes as arguments and arranges 175 | them in a *2 x 2* square, starting with the top-right corner, going 176 | clockwise, just like `mosaic` in Mission 1. 177 | 178 | ``` 179 | steps(rcross_bb, sail_bb, corner_bb, nova_bb); 180 | ``` 181 | 182 | ![](http://via.placeholder.com/350x150) 183 | 184 | ```` 185 | 186 | ## PROBLEMS 187 | 188 | Represents a set of PROBLEM elements. Required. 189 | 190 | ### Children 191 | 192 | [PROBLEM](#problem) 193 | 194 | ### Example 195 | 196 | ```xml 197 | 198 | ... 199 | ... 200 | ... 201 | 202 | ``` 203 | 204 | ## PROBLEM 205 | 206 | Represents a task within an assessment. Can have many. 207 | 208 | Required: at least one PROBLEM in the PROBLEMS element. 209 | 210 | ### Attributes 211 | 212 | | attribute | details | 213 | | ------------ | -------------------------------------------------------------------------------------------------------------------------------- | 214 | | maxxp | The maximum xp achievable for thie PROBLEM. XP earned by students will be proportional to the grade as graded by the autograder. | 215 | | type | The type of this question. Can be "programming", "mcq" or "voting". | 216 | | showsolution | Default false; If value is string "true", the solution string is shipped to web client.
In a PROBLEM of type "mcq', the solution is used on the frontend to determine if the student's answer is correct (and to provide immediate visual feedback to the student by highlighting the selection green or red). This can be used together with the attribute `blocking` to ensure students answer MCQ questions correctly before proceeding to the next question. In the event `showsolution` is "false" and `blocking` is "true", the frontend is unable to verify the student's MCQ answer, and will allow him/ her to proceed after making any selection.
In a PROBLEM of type "programming", the solution string, if sent, is currently NOT displayed to the student on the frontend. However, this might be subject to changes in the future, and the documentation will be updated accordingly here. Do note that more astute students might open the browser's network tab to view the solution string directly if it is sent. | 217 | | blocking | Default false; If value is string "true", the question is blocking; must be answered correctly to proceed to next question | 218 | 219 | ### Children 220 | 221 | [TEXT](#text), [SNIPPET](#snippet), [CHOICE](#choice), [VOTING](#voting), [DEPLOYMENT](#deployment), [GRADERDEPLOYMENT](#graderdeployment) 222 | 223 | #### programming 224 | [TEXT](#text), [SNIPPET](#snippet), [DEPLOYMENT](#deployment), [GRADERDEPLOYMENT](#graderdeployment) 225 | #### mcq 226 | [TEXT](#text), [CHOICE](#choice) 227 | #### voting 228 | [TEXT](#text), [SNIPPET](#snippet), [VOTING](#voting), [DEPLOYMENT](#deployment), [GRADERDEPLOYMENT](#graderdeployment) 229 | 230 | ### Example 231 | 232 | ```xml 233 | 234 | Your first task shall be to practise writing comments. 235 | ... 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | You can now vote on the most beautiful runes made by your fellow students! 247 | 248 | ... 249 | 250 | ``` 251 | 252 | ## CHOICE 253 | 254 | Represents an option in a [PROBLEM](#problem) of type "mcq". Required for PROBLEM elements of type "mcq". Can have many. 255 | 256 | ### Attributes 257 | 258 | | attribute | details | 259 | | --------- | --------------------------------------------------------------------------------------------------------- | 260 | | correct | If this is the correct option for the PROBLEM. Can be "true" or "false". | 261 | | hint | The hint to show to the student should they select this CHOICE, and this CHOICE is not correct. Optional. | 262 | 263 | ### Example 264 | 265 | ```xml 266 | ... 267 | ... 268 | ... 269 | ... 270 | ``` 271 | 272 | ## VOTING 273 | 274 | Represents the configuration in a [PROBLEM](#problem) of type "voting". Required for PROBLEM elements of type "voting". Can only have one. 275 | 276 | ### Attributes 277 | 278 | | attribute | details | 279 | | --------- | --------------------------------------------------------------------------------------------------------- | 280 | | assessment_number | The assessment number that refers to the contest assessment for this voting assessment | 281 | | reveal_hours | The number of hours after the assessment close time before the leaderboard reveals for students
staff and admin can always see the leaderboard.| 282 | 283 | ### Example 284 | 285 | ```xml 286 | 287 | ``` 288 | 289 | ## SNIPPET 290 | 291 | Represents snippets of source programs in a [PROBLEM](#problem) of type "programming". Required for PROBLEM elements of type "programming". 292 | 293 | In a [PROBLEM](#problem) of type "voting", valid children are [PREPEND](#prepend) and [TEMPLATE](#template). Optional for PROBLEM elements of type "voting". 294 | 295 | ### Children 296 | 297 | [PREPEND](#prepend), [TEMPLATE](#template), [POSTPEND](#postpend), [TESTCASES](#testcases), [SOLUTION](#solution) 298 | 299 | ### Example 300 | 301 | ```xml 302 | 303 | ... 304 | 305 | ... 306 | ... 307 | ... 308 | 309 | ``` 310 | 311 | ## PREPEND 312 | 313 | Represents a program string to be prepended to student's code. Optional. 314 | 315 | ### VALUE 316 | 317 | A program string to be prepended to the student's code. 318 | 319 | Note that XML preserves whitespaces, so the indentations of the string in this value property will be exactly what is shown to the student; i.e. the programs you write here should start with an absolute indentation level of 0. In addition, you must escape predefined XML entities quot ("), amp (&), apos ('), li (<), and gt (>). 320 | 321 | ### EXAMPLE 322 | 323 | ```xml 324 | 325 | function predeclared_function() { 326 | do_something(); 327 | } 328 | 329 | ``` 330 | 331 | ## TEMPLATE 332 | 333 | Represents an answer template that will be provided to the student when they first load up an assessment or when they reset an assessment. Required. 334 | 335 | ### Value 336 | 337 | Text to be shown to the student, representing an answer template that will be shown when they first load up an assessment. 338 | 339 | ### Example 340 | 341 | ```xml 342 | 347 | ``` 348 | 349 | ## POSTPEND 350 | 351 | Represents a program string that is appended to the student code. Note that the postpend program string is only appended to student code during grading. Optional. 352 | 353 | ### VALUE 354 | 355 | A program string that is appended to the student code. 356 | 357 | ### EXAMPLE 358 | 359 | ```xml 360 | 361 | function postdeclared_function() { 362 | do_something_else(); 363 | } 364 | 365 | ``` 366 | 367 | ## TESTCASES 368 | 369 | Represents the test cases that are used to judge a student's code. Typically used together with serverside autograding (if configured). Optional. 370 | 371 | ### CHILDREN 372 | 373 | [PUBLIC](#public), [OPAQUE](#opaque), [SECRET](#secret) 374 | 375 | ### EXAMPLE 376 | 377 | ```xml 378 | 379 | ... 380 | ... 381 | ... 382 | ... 383 | ... 384 | ... 385 | 386 | ``` 387 | 388 | ## PUBLIC 389 | 390 | Represents a public test case. Public test cases will be sent to the client. Students can see the testcase program and run them to see the result. Optional. Can have many. 391 | 392 | ### Attributes 393 | 394 | | attribute | details | 395 | | --------- | ------------------------------------------------------------------------ | 396 | | answer | The answer to the particular test case. String format. Required. | 397 | | score | The weighted score to the particular test case. String format. Required. | 398 | 399 | ### VALUE 400 | 401 | The program string that calls the student-declared function. 402 | 403 | ### EXAMPLE 404 | 405 | ```xml 406 | sum(1,2); 407 | ``` 408 | 409 | ## OPAQUE 410 | 411 | Represents an opaque test case. Opaque test cases will be sent to the client. The test case programs will be hidden from the students, but they can still run them to see if they pass the test. Grader can view the test case program in the grading workspace. Optional. Can have many. 412 | 413 | ### Attributes 414 | 415 | | attribute | details | 416 | | --------- | ------------------------------------------------------------------------ | 417 | | answer | The answer to the particular test case. String format. Required. | 418 | | score | The weighted score to the particular test case. String format. Required. | 419 | 420 | ### VALUE 421 | 422 | The program string that calls the student-declared function. 423 | 424 | ### EXAMPLE 425 | 426 | ```xml 427 | sum(-2,2); 428 | ``` 429 | 430 | ## SECRET 431 | 432 | Represents a secret test case. Secret test cases will not be sent to students but will be sent to the grading workspace. Primarily used to add more testcases for serverside autograding. Optional. Can have many. 433 | 434 | ### Attributes 435 | 436 | | attribute | details | 437 | | --------- | ------------------------------------------------------------------------ | 438 | | answer | The answer to the particular test case. String format. Required. | 439 | | score | The weighted score to the particular test case. String format. Required. | 440 | 441 | ### VALUE 442 | 443 | The program string that calls the student-declared function. 444 | 445 | ### EXAMPLE 446 | 447 | ```xml 448 | sum(-2,2); 449 | ``` 450 | 451 | ## SOLUTION 452 | 453 | Represents a solution to the PROBLEM that may be provided to the module staff during manual grading, in the grading interface. Required. 454 | 455 | ### Value 456 | 457 | Working solution to be shown to the grading staff. 458 | 459 | This is also a good place to insert any messages (as comments) that you may wish to convey to module staff viewing this assessment. 460 | 461 | Note that XML preserves whitespaces, so the indentations of the string in this value property will be exactly what is shown to the student; i.e. the programs you write here should start with an absolute indentation level of 0. In addition, you must escape predefined XML entities quot ("), amp (&), apos ('), li (<), and gt (>). 462 | 463 | ### Example 464 | 465 | ```xml 466 | 467 | // [Marking Scheme] 468 | // 0 marks 469 | 470 | // flipping a picture vertically can be achieved 471 | // by first flipping it horizontally and then 472 | // turning the result upside_down (why?) (discuss 473 | // the usefulness of this comment! Focus: Does 474 | // it help the audience understand the program?) 475 | function flipvert(picture) { 476 | return turn_upside_down(flip_horiz(picture)); 477 | } 478 | // example usage 479 | show(flipvert(sail_bb)); 480 | 481 | ``` 482 | 483 | ## DEPLOYMENT 484 | 485 | Represents interpreter settings for the source interpreter of cadet. 486 | 487 | **Required** for each [TASK](#task), optional for each [PROBLEM](#problem). 488 | 489 | For a given PROBLEM, the following checks are performed to determine what interpreter settings should be used for the PROBLEM: 490 | 491 | If the PROBLEM has a child DEPLOYMENT, use that 492 | Otherwise, use the DEPLOYMENT which is a child of the TASK 493 | The missionType attribute was previously used by source-academy2, but is unused by cadet. 494 | 495 | ### Attributes 496 | 497 | | attributes | details | 498 | | ----------- | ----------------------------------------------------------------------------------------------------------------------------- | 499 | | interpreter | The Source chapter to use. | 500 | | variant | The Source variant to use; one of `wasm`, `lazy`, `non-det`, `concurrent`, `gpu`, `default`. Optional, defaults to `default`. | 501 | | exectime | Execution time limit, in milliseconds. Optional, defaults to 1000. | 502 | 503 | ### Children 504 | 505 | [IMPORT](#import), [EXTERNAL](#external), [GLOBAL](#global) 506 | 507 | ### Example 508 | 509 | ```xml 510 | 511 | 512 | beside 513 | make_cross 514 | 515 | 516 | draw_points_on 517 | draw_connected 518 | 519 | 520 | student_names 521 | list("Alpha Centauri", "007", "Gilgamesh"); 522 | 523 | 524 | ``` 525 | 526 | ## GRADERDEPLOYMENT 527 | 528 | Represents interpreter settings which override that of DEPLOYMENT, for the grader. Optional for both TASK and PROBLEM. 529 | 530 | For a given PROBLEM, the following checks are performed to determine what interpreter settings should be used for the grader: 531 | 532 | If the PROBLEM has a child GRADERDEPLOYMENT, use that 533 | Otherwise, if the PROBLEM has a child DEPLOYMENT, use that 534 | Otherwise, if the TASK has a child GRADERDEPLOYMENT, use that 535 | Otherwise, use the DEPLOYMENT which is a child of the TASK 536 | This element is useful for assessments that utilise imported modules which use browser based APIs such as WebGL or HTML5 Audio. Since the grader runs on a node environment, these APIs are not available to the grader. Hence, it may be useful to 'overwrite' these functions with mock node-friendly alternative functions. 537 | 538 | Examples include `show` from the runes module, `draw_connected` from the curves module, or `play` from the sound module. 539 | 540 | ### Attributes 541 | 542 | | attributes | details | 543 | | ----------- | -------------------------- | 544 | | interpreter | The source chapter to use. | 545 | 546 | ### Children 547 | 548 | [IMPORT](#import), [EXTERNAL](#external), [GLOBAL](#global) 549 | 550 | ### Example 551 | 552 | ```xml 553 | 554 | 555 | beside 556 | make_cross 557 | 558 | ... 559 | ... 560 | ... 561 | 562 | ``` 563 | 564 | ## IMPORT 565 | 566 | Represents a module to be exposed to the student. Optional. Can have many. The IMPORT mechanism is slated to replace the EXTERNAL mechanism in AY 20/21. 567 | 568 | ### Attributes 569 | 570 | | attributes | details | 571 | | ---------- | -------------------------------------------------------------------------------------------------- | 572 | | module | Path of the library, relative to `https://github.com/source-academy/assessments/tree/master/lib/`. | 573 | 574 | ### Children 575 | 576 | [SYMBOL](#symbol) 577 | 578 | ### Example 579 | 580 | ```xml 581 | 582 | beside 583 | make_cross 584 | 585 | ``` 586 | 587 | ## EXTERNAL 588 | 589 | Represents an "external" library to be exposed to the student. Optional. 590 | 591 | ### Attributes 592 | 593 | | attributes | details | 594 | | ---------- | -------------------------------------------------------------------------------------------------------- | 595 | | name | Name of the "external" library. Can be "NONE", "TWO_DIM_RUNES", "THREE_DIM_RUNES", "CURVES", or "SOUND". | 596 | 597 | ### Children 598 | 599 | [SYMBOL](#symbol) 600 | 601 | ### Example 602 | 603 | ```xml 604 | 605 | beside 606 | make_cross 607 | 608 | ``` 609 | 610 | ## SYMBOL 611 | 612 | Represents an identifier from the [IMPORT](#import)ed module, or [EXTERNAL](#external) library or [GLOBAL](#global) variables to be exposed through the Source implementation. Put simply, this declares a variable in the source context that points to an identically named variable in the window namespace. Optional. Can have many. 613 | 614 | The identifier exposed by the source interpreter will take the same name as the identifier it points to in the IMPORTed module. For example, the function `show` in Source will execute the function `show` in the specified IMPORTed module. 615 | 616 | ### Value 617 | 618 | Text representing a valid JavaScript identifier name for the symbol. 619 | 620 | ### Example 621 | 622 | ```xml 623 | beside 624 | make_cross 625 | ``` 626 | 627 | ## GLOBAL 628 | 629 | Represents a variable to be dumped into the window namespace. Optional. Can have many. 630 | 631 | This is useful to define functions or constants for the student's use, which are not provided by imported modules. For example, you may wish to expose a variable containing a list of names for the student to sort through in sorting missions. 632 | 633 | You may also use this to override some property of the window, perhaps originating from an IMPORTed module. 634 | 635 | ### Children 636 | 637 | [IDENTIFIER](#identifier), [VALUE](#value) 638 | 639 | ### Example 640 | 641 | ```xml 642 | 643 | student_names 644 | list("Alpha Centauri", "007", "Gilgamesh"); 645 | 646 | ``` 647 | 648 | ## IDENTIFIER 649 | 650 | Represents the identifier name of a GLOBAL variable. Required. 651 | 652 | ### Value 653 | 654 | Text representing a valid javascript identifier name for the GLOBAL variable. 655 | 656 | ### Example 657 | 658 | ```xml 659 | student_names 660 | ``` 661 | 662 | ## VALUE 663 | 664 | Represents the javascript value of a GLOBAL variable. Required. 665 | 666 | ### Value 667 | 668 | Text representing a valid JavaScript program to be eval'd. The return value of this evaluation is then taking to be the value of the GLOBAL variable. 669 | 670 | ### Example 671 | 672 | ```xml 673 | list("Alpha Centauri", "007", "Gilgamesh"); 674 | ``` 675 | 676 | ## Example Assessments XML 677 | 678 | ```xml 679 | 680 | 681 | 682 | 685 | 691 | 692 | Textbook Sections 1.1.1 to 1.1.2 693 | 694 | Welcome to your 99th mission! 695 | 696 | 697 | Welcome to this assessment! This is the *briefing*. 698 | 699 | This mission consists of **four tasks**. 700 | 701 | 1. A simple PROBLEM that uses the default DEPLOYMENT and GRADERDEPLOYMENT 702 | for its GRADER programs (source 1). 703 | 2. A sorting PROBLEM that uses it's own DEPLOYMENT AND GRADERDEPLOYMENT. 704 | Here, GLOBALs and IMPORT are used to pre-define lists for the students 705 | as well as the grader to test the functions with. 706 | 3. An MCQ question. 707 | 4. A question which makes use of an imported module, `cs1101s_1920/two_dim_runes`. 708 | The functions from the module are exposed to the Source 709 | interpreter's global namespace according to what is specified in the 710 | SYMBOL elements. 711 | 712 | 713 | 714 | 715 | 716 | Your first task is to define a function `sum` that adds two numbers together. 717 | 718 | 719 | 720 | 726 | 727 | 728 | sum(10, 10); 729 | sum(0, 0); 730 | sum(99, 1); 731 | sum(-10, 10); 732 | sum(-1, -1); 733 | sum(-99, 1); 734 | 735 | 736 | // [Marking Scheme] 737 | // You may subtract 1 from grade if the student does not use arrow functions. 738 | 739 | 740 | 741 | 742 | 743 | 744 | Now, sort a list by any means. You are provided a list of numbers to test 745 | your sort function out with. 746 | 747 | 748 | 749 | const numbers = list(7, 5, 3, 1); 750 | const bigNumbers = list(15, 14, 13, 12, 11, 10, 1, 2, 3, 4, 5, 9, 8, 7, 6); 751 | 752 | 760 | 761 | 762 | sort(numbers); 763 | sort(list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); 764 | 765 | 766 | 767 | 768 | show 769 | 770 | 771 | 772 | 773 | show 774 | x => x; 775 | 776 | 777 | 778 | 779 | 780 | 781 | What is the air-speed velocity of an unladen swallow? 782 | 783 | 5 meters per second 784 | 8 meters per second 785 | 11 meters per second 786 | 24 meters per second 787 | 788 | 789 | 790 | 791 | You'll use runes in your next mission. Why don't you give it a try? 792 | 793 | `show(heart_bb)` should give you something like this: 794 | 795 | ![](http://via.placeholder.com/350x150) 796 | ![](https://http.cat/200) 797 | 798 | 799 | 803 | 804 | 805 | 806 | beside 807 | make_cross 808 | 809 | 810 | show 811 | heart_bb 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | ## Submission 820 | 821 | Make sure that everything for your programs to work is on the left hand side 822 | and **not** in the REPL on the right! This is because only that program is 823 | used to assess your solution. 824 | 825 | This TEXT will not be shown in cadet, but may be useful in the generated pdf. 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | ``` 837 | -------------------------------------------------------------------------------- /educator/game/README.md: -------------------------------------------------------------------------------- 1 | # Source Academy Game - Storywriter guide 2 | 3 | ## Contents 4 | 5 | * [Getting Started](#getting-started) 6 | 7 | * [Story Simulator](#story-simulator) 8 | * [Checkpoint Simulator](#checkpoint-simulator) 9 | * [Object Placement](#object-placement) 10 | * [Asset Uploader](#asset-uploader) 11 | * [Chapter Simulator](#chapter-simulator) 12 | 13 | * [Txt Guide](#txt-guide) 14 | * [Getting Started](#getting-started) 15 | * [What's in a Checkpoint?](#whats-in-a-checkpoint) 16 | * [Key Concepts](#key-concepts) 17 | * [Default checkpoint](#default-checkpoint) 18 | * [Txt Format Guide](#txt-format-guide) 19 | * [Main .txt](#main-txt) 20 | * [Location Guide](#location-guide) 21 | * [Actions](#headerActions) 22 | * [Objects](#headerObjects) 23 | * [BoundingBoxes](#headerBoundingBoxes) 24 | * [Characters](#headerCharacters) 25 | * [Bgm](#headerBgm) 26 | * [Sfx](#headerSfx) 27 | * [Dialogue Guide](#dialogue-guide) 28 | * [Dialogue Header](#dialogue-header) 29 | * [Dialogue Body](#dialogue-body) 30 | * [Basic rule](#basic-rule) 31 | * [Dialogue Actions](#dialogue-actions) 32 | * [Speakers](#speakers) 33 | * [Parts and goto's](#parts-and-gotos) 34 | * [Prompts](#prompts) 35 | * [Interpolation](#interpolation) 36 | * [Action Guide](#action-guide) 37 | * [Action execution order](#action-execution-order) 38 | * [Entities that can trigger actions](#entities-that-can-trigger-actions) 39 | * [Actions API](#actions-api) 40 | * [Action Repeatability](#action-repeatability) 41 | * [Action Conditions](#action-conditions) 42 | * [Conditions API](#conditions-api) 43 | * [Entity Guide](#entity-guide) 44 | 45 | * [Sample Checkpoint](#sample-checkpoint) 46 | 47 | ## Getting Started 48 | 49 | Important keywords to know as a story writer 50 | 51 | * Source Academy Game 52 | * Interactive visual novel to complement students' learning 53 | * Comprised of [chapters](#chapters) 54 | 55 | * Chapters 56 | * Main division of the Source Academy game 57 | * Released on specified open date (can be specified in [Chapter Simulator](#chapter-simulator)) 58 | * Comprised of several [checkpoints](#checkpoints) 59 | 60 | * Checkpoints 61 | * Within a chapter, checkpoints are played in progression as previous checkpoint is completed. 62 | * Basic 'programmable' unit of Source Academy story; every checkpoint is specified using a text-based CSV 63 | * Checkpoint is a storywriter's tool to place the student in an entirely new scenario within the course of a single chapter. 64 | * Enables writers to provide students with different set of objectives and also a new map with a different set of locations/objects/dialogues to interact with. 65 | 66 | If you're looking to write your own checkpoint txt: 67 | 68 | * Refer to the following [Sample Checkpoint](https://github.com/source-academy/frontend/wiki/Game-:-Sample-Checkpoint) or download this [sample txt](https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/stories/1-settling-in.txt) for reference as you read the [txt guide](#txt-guide). 69 | 70 | * You may download the following [Source Academy Game Txt Syntax highlighter](https://github.com/source-academy/sa-game-syntax-highlighter) vs code extension to highlight your txt under the **Sa** language 71 | 72 | ## Authoring Workflow 73 | 74 | These are the steps in authoring a story: 75 | 76 | 1. Use [Object Placement](#object-placement) to design a scene, print the generated text file from the browser console log 77 | 2. Add dialogues and actions onto your checkpoint text file by following the [Txt Guide](#txt-guide) 78 | 3. Try out your checkpoint using [Checkpoint Simulator](#checkpoint-simulator) 79 | 4. When you're happy with your checkpoint text, upload your checkpoint text as an asset on S3 using [Asset Uploader](#asset-uploader) 80 | 5. After making 1 or more checkpoint text files, you may wrap and publish your chapter by providing title, open date, publish status, and component checkpoint files through the [Chapter Simulator](#chapter-simulator). 81 | 82 | ## Story Simulator 83 | 84 | Story Simulator provides a set of tools to help writers generate the .txt file and simulate a single checkpoint, which they can then upload. 85 | Story Simulator has various tools that you can use by clicking on their names on the Story Simulator Main Menu. 86 | 87 | ### Object Placement 88 | 89 | Enables you to rearrange objects, bounding boxes and background in the scene and capture their coordinates and asset paths. 90 | 91 | #### Tools available 92 | 93 | * At side panel: 94 | 1. **Asset Selection** - The Asset Selection on the side panel is a place to look for assets you'd like to place on scene. You can click to open/close folders and click on assets to select it. 95 | 2. **Asset Viewer** - Displays image that you selected with Asset Selection to let you visualise it before placing it on scene. 96 | 97 | * At game screen's Object Placement: 98 | 1. **Background Paint Bucket** - Paints background on scene. To use, select an image from the `/location` folder of the Asset Selection section and click on the paint bucket to see the new background. 99 | 2. **Add Selected Object** - Adds more foreground images to the scene. To use, select an object from any folder of the Asset Selection section and click on the paint bucket to see the new background. 100 | 3. **Bounding box** - Lets you draw bounding boxes. To use, click on the tool and drag to draw rectangles on scene. 101 | 4. **Drag or resize** - Lets you drag things around the scene. To use, click on the tool and start dragging objects and bounding boxes. ⌨️ Hint: Use the `[` and `]` keys to resize images and bounding boxes. 102 | 5. **Print coordinates** - Lets you see coordinates on hover and print them out in the console. To use, click and look at console to see the .txt 103 | 6. **Erase all** - Erases everything on scene. Be careful when using this as there is no Undo button. 104 | 105 | ### Checkpoint Simulator 106 | 107 | Runs a checkpoint txt file using actual game engine. You may either load your local text files to the browser or use existing S3 files 108 | 109 | 1. Choose a default (i.e. base) checkpoint file (from local or S3) 110 | 2. Choose a checkpoint txt file (from local or S3) 111 | 3. Click on 'Simulate Checkpoint' and play your story that combines these two text files. 112 | 113 | Note: Do note that your game state is not saved to backend and txts are not uploaded. You may upload them once you're satisfied using the [asset uploader](#asset-uploader). 114 | 115 | ### Asset uploader 116 | 117 | Enables you to upload and delete assets (images, sounds, and checkpoint .txts) that that are used by the game. 118 | 119 | #### Uploading files 120 | 121 | 1. Choose a folder that you'd like to upload your asset into. 122 | 2. Choose file or files that you want to upload. 123 | 3. Click on Upload image. 124 | 4. Refresh page to see your new asset in Asset Selection. 125 | 126 | Note: You may not overwrite existing files, but you can always delete them and then reupload them. This step is made so that you don't accidentally overwrite files. 127 | 128 | #### Deleting files 129 | 130 | 1. Click on the trash can icon to delete a file. 131 | 2. Confirm whether you actually want to delete the file. 132 | 133 | ### Chapter Simulator 134 | 135 | A place to control and simulate stories which are published to students. 136 | 137 | #### Editing/Creating a chapter 138 | 139 | 1. Use dropdown to choose a chapter you want to edit/ create. 140 | 2. Give a title for chapter 141 | 3. Choose open date for chapter 142 | 4. Choose a background image for the chapter 143 | 5. Choose and order the checkpoint text files that should make up that chapter (Possibly give your full chapter a go?) 144 | 6. Adjust whether or not this story should be published. 145 | 7. Hit Save to make changes to your chapter. 146 | 147 | ## Txt Guide 148 | 149 | A guide to writing the .txt read by the Source Academy game engine. 150 | 151 | ## What's in a Checkpoint? 152 | 153 | Definition and structure of a checkpoint 154 | 155 | As you may already know, checkpoint is a part of chapter, which are played in progression once the previous one has finished. 156 | 157 | A checkpoint is made up of (1) set of objectives and (2) a game map. 158 | 159 | **Objectives** 📝 160 | 161 | Refers to a set of goals that a player must achieve in order to clear the checkpoint. 162 | 163 | It can be a simple list such as: 164 | 165 | ``` 166 | talkToHartin 167 | goToClassRoom 168 | ``` 169 | 170 | Explanation: We define two **objectiveIds**, `talkToHartin` and `goToClassroom`. As the player interacts with various entities in the game, these objectives may be fulfilled through [actions](#action-guide). Once both these tasks are fulfilled by the player, the player can proceed to the next checkpoint. 171 | 172 | **Game Map** 🗺️ 173 | 174 | Refers to all the locations in the checkpoint and how each location is configured. Storywriters have great control when it comes to customising locations, such as which other locations it is connected to, what objects are present in it, or even game modes available, just to name a few customiseable aspects of a location. 175 | 176 | ## Key Concepts 177 | 178 | **Entities** 179 | 180 | Entity refers to an element in the game, such as a specific location, object, or dialogue. Refer to [Entity Guide](#entity-guide) to learn more about types of entities and what they mean in the game. 181 | 182 | **Actions** 🎬 183 | 184 | Actions are the main drivers of a story. They are the storywriters' tool or "Source"😉 to enable the game to progress based on player choices. 185 | 186 | * How actions are triggered: Storywriters can attach actions to entities. For example, attaching action to a location causes the action to be performed when location is visited while attaching actions to objects causes action to be performed when object is clicked. Look out for 🎬 to see whether objects can have actions. 187 | * What actions do: Using actions, storywriters can cause new objects and dialogues to be added to the map, move the player to a different location, mark objectives as "complete" and much more. 188 | * Storywriters can specify whether the action occurs just once or many times. 189 | * See [Action Guide](#action-guide) for more information. 190 | 191 | **Ids** 192 | 193 | Each entity such has its own id. Storywriters typically provide these in order to refer to a specific entity. 194 | 195 | * Example: `mainDoor1` could refer to one particular instance of a door image that is located in the center of the Hallway. 196 | * Typically written in camelCase. 197 | * Ids can have types such as **locationId**, **objectId**, etc. depending on the type of entity it is referring to. 198 | * Warning❗ Ids are unique across the entire checkpoint. Even though id's have different types, you cannot have a character with **characterId** of `car` and an object with **objectId** of `car` too. 199 | 200 | ## Default checkpoint 201 | 202 | All checkpoints inherit the `/stories/defaultCheckpoint.txt` in S3, sample [here](https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/stories/defaultCheckpoint.txt). 203 | 204 | This reduces the need to redeclare locations and items that are present throughout the game. 205 | 206 | You may overwrite this by uploading with the `defaultCheckpoint.txt` filename. 207 | 208 | ## Txt Format Guide 209 | 210 | A little guide on the unique .txt syntax 211 | 212 | ### 1. Types of listing 213 | 214 | There are two types of listing 215 | 216 | #### point-listing 217 | 218 | Vertical listing of items separated by newlines 219 | 220 | Example: 221 | 222 | ``` 223 | item1 224 | item2 225 | item3 226 | ``` 227 | 228 | #### comma-listing 229 | 230 | Horizontal listing of items separated by commas 231 | 232 | Example: 233 | 234 | ``` 235 | item1, item2, item3 236 | ``` 237 | 238 | ### 2. Paragraphs 239 | 240 | The .txt uses Python-like paragraph format 241 | 242 | A paragraph is made up of a **header** and a **body**. 243 | 244 | ``` 245 | header 246 | body 247 | body 248 | body 249 | ``` 250 | 251 | Storywriters can create paragraph bodies by indenting with 4 spaces or 1 tab 252 | 253 | Example: 254 | 255 | ``` 256 | header1 257 | line3 258 | line4 259 | header5 260 | line6 261 | line7 262 | line8 263 | line9 264 | line10 265 | line11 266 | line12 267 | ``` 268 | 269 | In the above example, there are two main headers, `header1` and `header5`, each containing a body of text underneath. 270 | 271 | * `header1`'s body is a point-listing made up of just 2 points: `line3` and `line4` 272 | * `header5`'s body is a point-listing 4 points: `line6`, `line9`, `line10`, and `line12` 273 | * We can also nest further things underneath one point. `line6`'s body is a point-listing of 2 points: `line7` and `line8`, while `line10`'s body is a point-listing of 1 points: `line11`. 274 | 275 | ### 3. Txt Lines 276 | 277 | Lines refer to all non-empty lines in the text file, whichever paragraph they are in. A txt line is typically one of the following: 278 | 279 | * An id such as `studentRoom` 280 | * A category such as `characters` 281 | * A CSV (see [CSV format](#4-CSV-format)) 282 | * A configuration line (see [Configuration Line](#5-configuration-line)) 283 | 284 | ### 4. CSV format 285 | 286 | This format specifies properties for an entity. 287 | 288 | Examples: 289 | 290 | ``` 291 | cheiftain, Chieftain, happy, left 292 | ``` 293 | 294 | ``` 295 | myChair, /objects/chair.png, 100, 100 296 | ``` 297 | 298 | CSV's describes an entity (e.g. character or object)'s properties. The order of properties matters. The proper CSV format must be followed in order to accurately describe an entity. 299 | 300 | ### 5. Configuration line 301 | 302 | This format specifies the value(s) for a certain key, using a `:` symbol. 303 | 304 | Examples: 305 | 306 | ``` 307 | startingLoc: studentRoom 308 | ``` 309 | 310 | ``` 311 | modes: talk, move, explore 312 | ``` 313 | 314 | This line describes the value for a particular configuration such as the value of `startingLoc` (starting location) or the list of game modes in a location. In case the value is a comma-listing, the order of values typically don't matter. 315 | 316 | ### 6. Comments 317 | 318 | As in most programming languages, you can comment out lines or sections of lines using `//` and `/* */`. 319 | 320 | #### single-line comments 321 | 322 | `//` ignores all characters occuring after it in the same line. 323 | 324 | ``` 325 | objectives 326 | checkedScreen 327 | // talkedToLokKim1 328 | // talkedToLokKim2 329 | // talkedToLokKim3 330 | ``` 331 | 332 | #### multi-line comments 333 | 334 | `/* */` ignores characters between `/*` and `*/`, possibly spanning multiple lines. 335 | 336 | ``` 337 | objectives 338 | checkedScreen 339 | /* talkedToLokKim1 340 | talkedToLokKim2 341 | talkedToLokKim3 */ 342 | ``` 343 | 344 | ## Main .txt 345 | 346 | The following must be specified in the main outermost layer of the .txt 347 | 348 | ### Main Txt Configuration lines 349 | 350 | |Key|Value(s)| Requirements for value | 351 | |:--|:--|:--| 352 | |`startingLoc`| The starting location of the player upon entering the chapter | Must be an existing location id | 353 | 354 | ### Main Txt Paragraphs 355 | 356 | The following are paragraphs present in the outermost layer of .txt 357 | 358 | #### Header:`objectives` 359 | 360 | #### Body 361 | 362 | Point-listing of **objectiveIds** that players must accomplish to complete the checkpoint. 363 | 364 | Example: 365 | 366 | ``` 367 | objectives 368 | talkToHartin 369 | solveThePuzzle 370 | ``` 371 | 372 | Explanation: We define that players must accomplish the tasks `talkToHartin` and `solveThePuzzle` to proceed to next checkpoint. 373 | 374 | *** 375 | 376 | #### Header:`gameStartActions` 377 | 378 | #### Body 379 | 380 | Point-listing of actions that execute whenever student revisits the checkpoint. 381 | 382 | Example: 383 | ``` 384 | gameStartActions 385 | show_dialogue*(welcomeBack) 386 | ``` 387 | 388 | Explanation: Whenever the student comes back to play this game, he is shown the `welcomeBack` message. 389 | 390 | *** 391 | 392 | #### Header:`checkpointCompleteActions` 393 | 394 | #### Body 395 | 396 | Point-listing of actions that execute once student has completed the checkpoint. 397 | 398 | Example: 399 | 400 | ``` 401 | checkpointCompleteActions 402 | show_dialogue(wellDone) 403 | ``` 404 | 405 | Explanation: When the student has completed the checkpoint, he is shown the `welcomeDone` message. 406 | 407 | *** 408 | 409 | #### Header: `locations` 410 | 411 | #### Body 412 | 413 | Point-listing of CSVs to declare locations present in the checkpoint. 414 | 415 | CSV format: `locationId, location asset path, location name, asset type(optional), number of frames(optional)` 416 | 417 | | Property | Meaning | 418 | |:--|:--| 419 | | locationId | Declaration of new location with that `locationId` 420 | | location asset path | The path to an image file to be used in painting the background of the location | 421 | | location name | display for that location when players click on "Move" | 422 | | asset type | `Image` or `Sprite` type. Asset type can be omitted if type is `Image` but is mandatory for `Sprite` | 423 | | number of frames | Number of frames of a spritesheet. Required only for `Sprite` assets | 424 | 425 | Example: 426 | ``` 427 | locations 428 | studentRoom, /locations/room.png, Student Room, Sprite, 11 429 | hallway, /locations/hallaway.png, Hallway 430 | ``` 431 | 432 | Explanation: We create two locations, one with **locationId** `studentRoom` that uses the spritesheet `/locations/room.png` with 11 frames as an animated background and has the display name `Student Room`, and another with **locationId** `hallway` that uses `/locations/hallway.png` as background and has the display name `Hallway` 433 | 434 | Note: Animated background spritesheets must have frames with dimensions 1920x1080 435 | 436 | *** 437 | 438 | #### Header:`` 439 | 440 | Use one of the **locationIds** you defined previously under `locations` paragraph 441 | 442 | #### Body 443 | 444 | Nested paragraph describing a specific location 445 | 446 | Example: 447 | 448 | ``` 449 | studentRoom 450 | modes: ... 451 | objects 452 | ... 453 | characters 454 | ... 455 | ``` 456 | Refer to [Location Guide](#location-guide) for more information on writing location paragraphs. 457 | 458 | *** 459 | 460 | #### Header:`dialogues` 461 | 462 | #### Body 463 | 464 | Point-listing of dialogue (paragraphs) that can be brought up 465 | 466 | Example: 467 | 468 | ``` 469 | dialogues 470 | uninhabited, The Uninhabited Planet 471 | ... 472 | newBegin, A new beginning 473 | ... 474 | ``` 475 | 476 | Refer to [Dialogue Guide](#dialogue-guide) for more information on writing dialogues. 477 | 478 | ## Location Guide 479 | 480 | How to write paragraphs describing a certain location. 481 | 482 | Each location paragraph is headed by the `locationId` of the location that you want to describe. 483 | 484 | The following must be specified in the body of a location: 485 | 486 | ### Configuration lines 487 | 488 | |Key|Value(s)| Requirements | 489 | |:--|:--|:--| 490 | |`modes`| Comma-listing of the [game modes](#mode) available in the chapter | Every mode must be one of the following: `talk`, `explore`, `move`| 491 | |`talkTopics`| Comma-listing of [talk topics](#talkTopic) available in a location, i.e. dialogues that players can choose from when click on "Talk" | Must be valid **dialogueIds** | 492 | |`nav`| Comma-listing of other locations that this location is connected to. |Must be valid **locationIds** | 493 | 494 | ### Paragraphs 495 | 496 | Paragraphs in the body of the location paragraph. 497 | 498 | *** 499 | 500 | #### Header:`actions` 501 | 502 | #### Body 503 | Point-listing of actions 🎬 that occur when location is visited. 504 | 505 | Example: 506 | 507 | ``` 508 | actions 509 | show_dialogue(youveArrived) 510 | make_object_glow(pen) 511 | ``` 512 | 513 | Refer to [Action Guide](#action-guide) for more details on how to describe an action. 514 | 515 | *** 516 | 517 | #### Header:`objects` 518 | 519 | #### Body 520 | 521 | Point-listing of CSVs of [objects](#object) in the location. 522 | 523 | CSV format: `+objectId, object asset path, x, y, width(optional), height(optional), asset type(optional), number of frames(optional)` 524 | 525 | | Property | Meaning | 526 | |:--|:--| 527 | | + | Presence of object at the start of the checkpoint. Put a plus sign if you want the object to appear initially when checkpoint begins, drop the plus sign if you'd like to add it later. 528 | | objectId | Declaration of new [object](#object) with objectId of `objectId` | 529 | | object asset path | The path to the image file to be used in rendering the object in the location | 530 | | x | x-coordinate of centre of the image | 531 | | y | y-coordinate of centre of image | 532 | | width | width of the image, required for `Sprite` assets | 533 | | height | height of the image, required for `Sprite` assets | 534 | | asset type | `Image` or `Sprite` type. Asset type can be omitted if type is `Image` but is required for `Sprite` | 535 | | number of frames | Number of frames of a spritesheet. Required only for `Sprite` assets | 536 | 537 | Example: `+mainDoor1, /objects/door.png, 10, 20, 30, 40, Sprite, 11` 538 | 539 | Explanation: In the location, we display an animated object with **objectId** `mainDoor1` that uses the spritesheet `/objects/door.png`, with 11 frames and each frame of size 30 by 40 pixels, as its texture and is rendered using the coordinates (10, 20). 540 | 541 | Each object CSV line may have nested point-listed [actions](#action-guide) 🎬 underneath, specifying what actions are triggered when object is clicked. 542 | 543 | *** 544 | 545 | #### Header:`boundingBoxes 546 | 547 | #### Body 548 | 549 | Point-listing of CSVs of [bounding boxes](#boundingBox) in the location. 550 | 551 | CSV format: `+bboxId, x, y, width, height` 552 | 553 | | Property | Meaning | 554 | |:--|:--| 555 | | + | Presence of boundingbox at the start of the checkpoint. Put a plus sign if you want the [bounding box](#boundingBox) to appear initially when checkpoint begins, drop the plus sign if you'd like to add it later. 556 | | bboxId | Declaration of new boundingBox with bboxId of `bboxId` | 557 | | x | x-coordinate of centre of the rectangle | 558 | | y | y-coordinate of centre of rectangle | 559 | | width | width of the rectangle | 560 | | height | height of the rectangle | 561 | 562 | Example: `+bbox1, 10, 20, 30, 40` 563 | 564 | Explanation: In the location, we draw an invisible, possibly clickable rectangle with **bboxId** `bbox1` with coordinates (10, 20) and size 30 by 40 pixels. 565 | 566 | Each object CSV line may have nested point-listed [actions](#action-guide) 🎬 underneath, specifying what actions are triggered when boundingBox is clicked. 567 | 568 | *** 569 | 570 | #### Header:`characters` 571 | 572 | #### Body 573 | 574 | Point-listing of CSVs of [characters](#character) in the location. 575 | 576 | CSV format: `+characterId and assetPath, character name, default expression, default position` 577 | 578 | | Property | Meaning | 579 | |:--|:--| 580 | | + | Presence of character at the start of the checkpoint. Put a plus sign if you want the [character](#character) to appear initially when checkpoint begins, drop the plus sign if you'd like to hide the character or add him later. 581 | | characterId and assetPath | Declaration of new characterId. Since characters are unique and cannot have multiple instances, the id has to match the asset path (which is the folder name inside `/characters` folder) 582 | | character name | The display name to show in the dialogue speaker box if ever that character has dialogues | 583 | | default expression | The expression for this character initially. Must match one of the filenames 584 | | default position | Position to render the character originally. May be one of `left`, `right`, or `center` | 585 | 586 | Example: `+chieftain, Chieftain, happy, left` 587 | 588 | Explanation: In the location, we display `Chieftain` with **characterId** `chieftain` that uses `/characters/chieftain` folder as source of images, with `happy.png` being his original expression and is rendered on the left side of the screen. 589 | 590 | *** 591 | 592 | #### Header:`bgm` 593 | 594 | #### Body 595 | 596 | Point-listing of CSVs of [bgm](#bgm) in the location. 597 | 598 | CSV format: `bgmId, bgm asset path, volume` 599 | 600 | | Property | Meaning | 601 | |:--|:--| 602 | | bgmId | Declaration of new bgmId | 603 | | asset path | The path to the background music to be used in rendering the object in the location | 604 | | volume | Volume of this background music | 605 | 606 | Example: `heavyHitter, /bgm/HeavyHitter.mp3, 0.5` 607 | 608 | Explanation: We declare the background music with **bgmId** `heavyHitter` that uses `/bgm/HeavyHitter.mp3` as source of background music and volume of 0.5. 609 | 610 | Note: The first background music declared is made default for the location. 611 | 612 | *** 613 | 614 | #### Header:`sfx` 615 | 616 | #### Body 617 | 618 | Point-listing of CSVs of [sfx](#sfx) in the location. 619 | 620 | CSV format: `sfxId, sfx asset path, volume` 621 | 622 | | Property | Meaning | 623 | |:--|:--| 624 | | sfxId | Declaration of new sfxId | 625 | | asset path | The path to the sound effect to be used in rendering the object in the location | 626 | | volume | Volume of this sound effect | 627 | 628 | Example: `card, /sfx/card.mp3, 0.5` 629 | 630 | Explanation: We declare the sound effect with **sfxId** `card` that uses `/sfx/card.mp3` as source of background music and volume of 0.5. 631 | 632 | ## Dialogue Guide 633 | 634 | Crafting individual dialogue paragraphs under the `dialogues` paragraph 635 | 636 | ### Dialogue Header 637 | 638 | The header for a dialogue is a CSV with format: `dialogueId, title(optional)` 639 | 640 | Example: 641 | 642 | ``` 643 | planetXrk, What happened to the planet, Scottie? 644 | 645 | ``` 646 | 647 | Explanation: We define a dialogue with the **dialogueId** `planetXrk`. It has the title `What happened to the planet, Scottie?`. The title is will appear under the "Talk" menu if the dialogue is a [talk topic](#talkTopic) under a location. 648 | 649 | Note: Although this is a CSV, you can put commas in the title, this is fine. 650 | 651 | ### Dialogue Body 652 | 653 | Writing dialogue bodies are quite simple, much like writing a script for a play. 654 | 655 | Example: 656 | 657 | ``` 658 | @scottie, happy, left 659 | It has been a while since you last set foot on the ship. 660 | I'm so happy you've arrived. 661 | @you 662 | Thanks, Scottie! It was my pleasure. 663 | ``` 664 | 665 | #### Basic rule 666 | 667 | The simplest body is just a point-listing of lines to be spoken in the dialogue. 668 | 669 | #### Dialogue Actions 🎬 670 | 671 | You may nest point-listed actions underneath any line in the dialogue. This causes the actions to be triggered when dialogue line is spoken. 672 | 673 | ❗You may not perform the following actions during a dialogue. 674 | 675 | * `show_dialogue` - Dialogue is already playing. Use [goto](#parts-and-gotos)'s instead. 676 | 677 | #### Speakers 678 | 679 | You can change the speaker by writing a change-speaker CSV which starts with an `@` symbol 680 | 681 | CSV Format: `@characterId, expression(optional), position(optional)` 682 | 683 | |Property|Meaning| 684 | |:--|:--| 685 | | characterId | characterId of the speaker | 686 | | expression | Expression of the speaker. Has to be one of the expressions in the folder. Defaults to speaker's default expression if not specified | 687 | | position | Position of speaker on the map. One of `left`, `right`, `center`. Defaults to speaker's default position if not specified.| 688 | 689 | Example: `@beat, happy, left` 690 | 691 | Explanation: This line changes the speaker to a `beat` as described in any location's `characters` list, whose expression is happy and rendered on the left of the screen. 692 | 693 | ❗Make sure you have the character somewhere on the map first before making him a speaker, even if he's hidden or in another location. 694 | 695 | Note: You may use the following special speakers in place of the speaker CSV 696 | 697 | * `@you` - will make students' name appear 698 | * `@narrator` - will speaker box and speaker avatar disappear 699 | 700 | #### Parts and goto's 701 | 702 | You can specify parts of a dialogue by numbering lines using integers. 703 | 704 | Example: 705 | 706 | ``` 707 | 9 708 | Welcome to Source Academy 709 | goto 2 710 | 711 | 1 712 | You will never reach this part. 713 | 714 | 2 715 | You have reached part two. 716 | ``` 717 | 718 | Explanation: This dialogue has three parts. Part `9`, being listed first, will be played first. After playing `Welcome to Source Academy`, it reaches `goto 2`. This means the dialogue will now play part `2` - `You have reached part two`. That's the end. Part `1` will never be reached. 719 | 720 | #### Prompts 721 | 722 | You can also use user prompts to jump between dialogue parts, based on player choice. 723 | 724 | Example: 725 | 726 | ``` 727 | 1 728 | @narrator 729 | Welcome to Source Academy 730 | prompt: Which part next? 731 | Part 2 -> goto 2 732 | Part 3 -> goto 3 733 | Again! -> goto 1 734 | 2 735 | @narrator 736 | This is part 2. 737 | 3 738 | @narrator 739 | This is part 3. 740 | ``` 741 | 742 | Explanation: This dialogue again has 3 parts. After playing `Welcome to Source Academy`, the player sees a user prompt with the title `Which part next?` and 3 options: `Part 2`, `Part 3` and `Again!`. If the user selects `Part 2` or `Part 3`, parts `2` or `3` of the dialogue will be played respectively. If the user selects `Again!`, all of part `1` (including the prompt) will be played again. 743 | 744 | Note: Prompt boxes have fixed size. Although no hard character limits are enforced, the following recommended limits should be adhered to, to avoid overflow: 745 | 746 | * Prompt title text: 70 characters 747 | * Prompt choice text: 15 characters 748 | * Number of prompt choices: 5 749 | 750 | #### Interpolation 751 | 752 | You may interpolate student's name into the script using `{name}` which gets replaced with their Luminus names. 753 | 754 | ## Action Guide 755 | 756 | As we've seen, actions can be performed by various entities, such as locations, objects, bounding boxes, and even during dialogues. 757 | 758 | ### Action execution order 759 | 760 | If there is a listing of many actions, they are performed sequentially. 761 | 762 | ### Entities that can trigger actions 763 | 764 | | Entity | How to specify/attach action | When action is triggered| 765 | |:--|:--|:--| 766 | |Locations | Nest point-listed actions under the location paragraph's `action` header | When location is visited| 767 | |Objects | Nest point-listed actions under an object CSV line | When object is clicked during Explore mode | 768 | |BoundingBoxes | Nest point-listed under a boundingBox CSV line | When boundingBox is clicked during Explore mode | 769 | |Dialogue | Nest point-listed actions under any line in a dialogue body | Right after dialogue line is played | 770 | 771 | ### Actions API 772 | 773 | *** 774 | 775 | ##### `complete_objective(taskId)` 776 | 777 | Marks task with `taskId` in the checklist as accomplished 778 | 779 | Example: `complete_objective(talkToChieftain)` 780 | 781 | Explanation: When this action is executed, the task `talkToChieftain` in Objectives is marked as completed 782 | 783 | *** 784 | 785 | ##### `preview_location(locationId)` 786 | 787 | Previews a different location on the map 788 | 789 | Example: `preview_location(crashsite)` 790 | 791 | Explanation: When this action is executed, players will be shown the background and objects inside the `crashsite` location. 792 | 793 | ❗Warning: This is only a preview used for effect purposes. Internally, the player still is inside the original location. 794 | 795 | *** 796 | 797 | ##### `add_item(category, locationId, entityId)` 798 | 799 | ##### `remove_item(category, locationId, entityId)` 800 | 801 | Adds or removes an item with id `entityId` of category `category` from a location with id `locationId` 802 | 803 | List of possible categories and corresponding entity id. 804 | 805 | | Category | Entity Id | 806 | |:--|:--| 807 | | `objects` | objectId | 808 | | `dialogues` | dialogueId | 809 | | `boundingBoxes` | bboxId | 810 | | `navigation` | locationId | 811 | 812 | *** 813 | 814 | ##### `start_animation(objectId / locationId, startFrame, frameRate)` 815 | 816 | ##### `stop_animation(objectId / locationId)` 817 | 818 | Start and stop an object or background animation. 819 | 820 | Examples: 821 | `start_animation(yourRoom, 3, 20)` 822 | `stop_animation(yourRoom)` 823 | 824 | Explanation: 825 | 826 | * The first action acts on an entity with id `yourRoom` (entity must be an `objectId` or `locationId`). It plays an animation starting at the 3rd frame in the spritesheet and runs it at 20 frames per second. `yourRoom` must have been declared to be a `Sprite`. 827 | * The second action acts on the same entity with id `yourRoom` (entity must be an `objectId` or `locationId`). It stops the `yourRoom` animation if it was playing. 828 | 829 | *** 830 | 831 | ##### `change_background(locationId)` 832 | 833 | Changes the background of the scene to the background of a particular locationId as specified under main .txt's `locations` paragraph. 834 | 835 | *** 836 | 837 | ##### `show_object_layer(show?)` 838 | 839 | Shows or hides the object layer depending on whether show is 'true' or 'false'. Usually used to accompany `change_background` to create an effect. 840 | 841 | *** 842 | 843 | ##### `show_dialogue(dialogueId)` 844 | 845 | Brings up the dialogue with dialogueId `dialogue` as specified under the main `dialogues` paragraph. 846 | 847 | *** 848 | 849 | ##### `add_mode(locationId, mode)` 850 | 851 | ##### `remove_mode(locationId, mode)` 852 | 853 | Adds or removes a [game mode](#mode) from a location with locationId `locationId`. 854 | 855 | *** 856 | 857 | ##### `add_popup(objectId, position, duration?, size?)` 858 | 859 | Adds a popup showing the image of `objectId` on a position (`left`, `right`, or `middle`) for an optional duration of `duration` milliseconds with an optional size (`small`, `medium`, or `large`) 860 | 861 | *** 862 | 863 | ##### `delay(seconds)` 864 | 865 | Delay the execution of subsequent actions and dialogue by the specified number of seconds. 866 | 867 | *** 868 | 869 | ##### `make_object_glow(objectId, turnOn?)` 870 | 871 | If an object with objectId `objectId` is visible on screen, then it will glow yellow to draw players' attention. Optional parameter `turnOn` can either be true or false to turn on or turn off the glow respectively. 872 | 873 | *** 874 | 875 | ##### `make_object_blink(objectId, turnOn?)` 876 | 877 | If an object with objectId `objectId` is visible on screen, then it will blink to draw players' attention. Optional parameter `turnOn` can either be true or false to turn on or turn off the glow respectively. 878 | 879 | *** 880 | 881 | ##### `play_bgm(bgmId)` 882 | 883 | Changes background music to bgmId `bgmId`. 884 | 885 | *** 886 | 887 | ##### `play_sfx(sfxId)` 888 | 889 | Plays background music with sfxId `sfxId`. 890 | 891 | *** 892 | 893 | ##### `move_character(characterId, locationId, position?)` 894 | 895 | Moves a character from its original location to a new location. You may also change its default position (left, right, center) 896 | 897 | *** 898 | 899 | ##### `update_character(characterId, expression)` 900 | 901 | Changes the default expression of a character. 902 | 903 | *** 904 | 905 | ### Action Repeatability 906 | 907 | By default, actions are only performed once the first time they are triggered. Say, you want `show_dialogue(hi)` to occur every time an object is clicked. You can use the asterisk symbol to mark them as repeatable `*` 908 | 909 | Example: `show_dialogue*(hi)` 910 | 911 | Explanation: The action `show_dialogue*(hi)` will be performed every time object is clicked. 912 | 913 | ### Action Conditions 914 | 915 | Action Conditions are used to specify under which precondition an action can performed. They can be written as if clauses right next to the actions. 916 | 917 | Example: `show_dialogue(welcome) if checklist.talkToChieftain` 918 | 919 | Explanation: The action will be the first time it's triggered and `talkToChieftain` is completed. 920 | 921 | Example: `show_dialogue*(welcome) if checklist.talkToChieftain` 922 | 923 | Explanation: The action will be performed every time it's triggered as long as `talkToChieftain` task has been completed. 924 | 925 | You may chain multiple conditions using the keyword `AND` 926 | 927 | Example: `show_dialogue*(welcome) if checklist.talkToChieftain AND userState.collectibles.cookie` 928 | 929 | Explanation: The action will be performed only if `talkToChieftain` task has been completed, and user has the `cookie` under his collectibles list. 930 | 931 | #### Conditions API 932 | 933 | ##### `checklist.` 934 | 935 | ##### `userstate.collectibles.` 936 | 937 | ## Entity Guide 938 | 939 | What do we mean when we refer to...? 940 | 941 | ### objective 942 | 943 | One of the tasks the player has to complete to finish the checkpoint 944 | 945 | ### location 946 | 947 | One of the places players can to navigate to 948 | 949 | ### mode 950 | 951 | Choices of what activities players can do upon visiting a location. 952 | 953 | One of the following: `talk`, `explore`, `move` 954 | 955 | ### dialogue 956 | 957 | A list of lines containing speaker and sequence of spoken lines. 958 | 959 | ### object 960 | 961 | An image that is drawn in a certain location. This may or not be interactive in Explore Mode. 962 | 963 | ### character 964 | 965 | A character (avatar) present in a certain location. May also be used as speaker in the dialogue. 966 | 967 | ### boundingBox 968 | 969 | An invisible rectangle that players may possibly be able to interact with in Explore Mode. 970 | 971 | ### talkTopic 972 | 973 | One of the topics the player can talk about in Talk Mode. Specified using a dialogue. 974 | 975 | ## Sample Checkpoint 976 | 977 | ``` 978 | startingLoc: normal 979 | 980 | objectives 981 | talk 982 | 983 | gameStartActions 984 | show_dialogue*(unwelcome) if !userstate.assessments.301 985 | show_dialogue(welcome) if userstate.assessments.301 986 | 987 | checkpointCompleteActions 988 | show_dialogue(done) 989 | 990 | locations 991 | normal, /locations/yourRoom-dim/normal.png, Locations Your Room Dim Normal Png 992 | 993 | normal 994 | modes: explore, talk 995 | talkTopics: whatToDo 996 | actions 997 | show_dialogue(welcome) 998 | objects 999 | +emergency1, /objects/cmd-chair03/emergency.png, 781, 531, 318, 398 1000 | +chieftain2, /avatars/chieftain/chieftain.angry.png, 1400, 526, 697, 744 1001 | boundingBoxes 1002 | +bbox#0, 536, 420, 373, 402 1003 | show_dialogue(click) 1004 | 1005 | characters 1006 | hartin-menz, Hartin, happy, left 1007 | 1008 | dialogues 1009 | welcome 1010 | Congrats on creating your scene 1011 | click 1012 | Invisible bounding box is right here 1013 | 1014 | whatToDo, Are you wondering what to do, Cadet? 1015 | @you 1016 | Hmm, there's nothing to do around here. 1017 | 1018 | @hartin-menz 1019 | There's plenty of things you can do! 1020 | ``` 1021 | -------------------------------------------------------------------------------- /educator/github/README.md: -------------------------------------------------------------------------------- 1 | **The feature "GitHub Classroom" as been removed from Source Academy. The feature didn't have any users and we felt that it complicated our development. 2 | If you land on this page through an active link, let us know via 3 | bug report in [Source Academy frontend](https://github.com/source-academy/frontend/issues). If you like the feature described below, let us know. Maybe you can get involved to bring it back?** 4 | 5 | # Overview 6 | 7 | This guide tells you how Source Academy with GitHub Classroom 8 | could be used for your course. The feature has been removed. Let 9 | us know in 10 | [Source Academy frontend](https://github.com/source-academy/frontend/issues) 11 | if you find it interesting or if you have any other feedback 12 | or suggestions. 13 | 14 | # Content 15 | 16 | - [Setting up course](#setting-up-course) 17 | - [Creating GitHub Classroom organization](#creating-github-classroom-organization) 18 | - [Authorizing Source Academy to access GitHub Classroom organization](#authorizing-source-academy-to-access-github-classroom-organization) 19 | - [Adding learner to GitHub Classroom organization](#adding-learner-to-github-classroom-organization) 20 | - [Creating course repository](#creating-course-repository) 21 | - [Creating assessment](#creating-assessment) 22 | - [Authoring assessment](#authoring-assessment) 23 | - [Opening Assessment Creator](#opening-assessment-creator) 24 | - [Editing starter code](#editing-starter-code) 25 | - [Editing multiple choice question](#editing-multiple-choice-question) 26 | - [Editing assessment briefing and task description](#editing-assessment-briefing-and-task-description) 27 | - [Adding and deleting task](#adding-and-deleting-task) 28 | - [Writing test case](#writing-test-case) 29 | - [Editing assessment metadata](#editing-assessment-metadata) 30 | - [Saving changes](#saving-changes) 31 | - [Using old XMLs](#using-old-xmls) 32 | - [Publishing assessment](#publishing-assessment) 33 | - [Turning assessment repository into template repository](#turning-assessment-repository-into-template-repository) 34 | - [Creating GitHub Classroom assessment](#creating-github-classroom-assessment) 35 | - [Adding assessment to Source Academy course](#adding-assessment-to-source-academy-course) 36 | - [Grading assessment](#grading-assessment) 37 | - [Closing course](#closing-course) 38 | - [Removing learners and repositories](#removing-learners-and-repositories) 39 | 40 | # Setting up course 41 | 42 | ## Creating GitHub Classroom organization 43 | 44 | 1. Navigate to the GitHub Classroom website at . 45 | 2. Sign in to GitHub. 46 | 3. Click on "New Classroom" and select "Create a New Organization". 47 | 4. Fill in the details of your classroom and confirm the creation of the Organization. Note that the organization name has to be prefixed with 'source-academy-course' for Source Academy to identify it. 48 | 49 | ## Authorizing Source Academy to access GitHub Classroom organization 50 | 51 | Source Academy might not be able to see your assessments if it is not given permission to access your organization's repositories. Please follow the steps below to set the permissions. 52 | 53 | 1. Go to and click on "Classrooms" at the top of the control bar. Click on "Log In" to login with GitHub through our website. By approving Source Academy, you add it to your list of personally approved apps. 54 | 2. On your account, navigate to Settings > Applications > Authorized OAuth Apps. 55 | 3. Click on the Source Academy app, then grant permission for your classroom application. 56 | 57 | ## Adding learner to GitHub Classroom organization 58 | 59 | Learners can currently be added only one at a time. 60 | 61 | 1. Ask your learner for their GitHub username. 62 | 2. Navigate to the GitHub page of your organization. Take note - this is not the GitHub Classroom page for the same organization. 63 | 3. Navigate to People > Invite Member and invite the learner to the organization. Make sure to invite them as member:\ 64 | ![Invite As Member](https://user-images.githubusercontent.com/47176493/122375134-8ac25380-cf95-11eb-9f0f-3ce067b981b1.png) 65 | You can control member permissions by navigation to Settings > Member privileges. 66 | 4. The learner will receive an invitation to join the organization in their email, which they should accept. 67 | 5. The learner will then be able to go to , click on "Classroom" and "Log In" with their GitHub account. They will be able to select your course and see the assessments you have created. Note that the assessment area will be empty before you have created any assessments. 68 | 69 | ## Creating course repository 70 | 71 | 1. Navigate to the Organization's GitHub page. 72 | 2. Create a new repository named 'course-info'. 73 | 3. In this repository, create a new file 'course-info.json'. 74 | 75 | A sample format for this file is detailed below: 76 | 77 | ```json 78 | course-info 79 | { 80 | "CourseName": "ReplaceWithCourseName", 81 | "types": 82 | [ 83 | { 84 | "typeName": "Missions", 85 | "assessments": 86 | [ 87 | { 88 | "title": "Mission1", 89 | "openAt": "2020-12-01T00:00:00+08:00", 90 | "closeAt": "2021-12-31T23:59:59+08:00", 91 | "published": "yes", 92 | "coverImage": "https://i.imgur.com/q2O4iwa.png", 93 | "shortSummary": "In this mission, you get introduced to visible functions, called Curves!", 94 | "acceptLink": "https://classroom.github.com/a/PyAUhdfe", 95 | "repoPrefix": "somePrefix" 96 | }, 97 | { 98 | "title": "Mission2", 99 | "openAt": "2020-12-01T00:00:00+08:00", 100 | "closeAt": "2021-05-30T23:59:59+08:00", 101 | "published": "yes", 102 | "coverImage": "https://avatars.githubusercontent.com/u/35620705?s=400&u=32f72fd1d65a0d6877ad1d5870ffa327dda754f1&v=4", 103 | "shortSummary": "This is a demo mission!", 104 | "acceptLink": "https://classroom.github.com/a/CxlqjLaP", 105 | "repoPrefix": "somePrefix2" 106 | } 107 | ] 108 | }, 109 | { 110 | "typeName": "Quests", 111 | "assessments": 112 | [ 113 | { 114 | "title": "Quest1", 115 | "openAt": "2020-12-01T00:00:00+08:00", 116 | "closeAt": "2021-12-31T23:59:59+08:00", 117 | "published": "yes", 118 | "coverImage": "URL_TO_IMAGE", 119 | "shortSummary": "A sample assessment that should show up.", 120 | "acceptLink": "URL_TO_GITHUB_CLASSROOM", 121 | "repoPrefix": "somePrefix3" 122 | } 123 | ] 124 | } 125 | ] 126 | } 127 | ``` 128 | 129 | The above example will display 2 Missions and 1 Quest on the learner's Source Academy frontend. 130 | 131 | | Property | Description | 132 | | ------------------ | ----------------------------------------------------------------------------- | 133 | | title | A string value with the display name of the assessment. | 134 | | openAt and closeAt | start and due dates of the assessment in ISO 8601 standard for Date and Time. | 135 | | published | "yes" or "no" value determines if the assessment is visible for learners. | 136 | | coverImage | A string value of image URL for cover image of the assessment. | 137 | | shortSummary | A string value that summarises the assessment. | 138 | | acceptLink | A string value of the assignment accept link on GitHub Classroom. | 139 | | repoPrefix | A string value given to all repositories generated from GitHub Classroom. | 140 | 141 | The value of "categoryDisplayName" can be changed to replace the assessment headers in the navbar. 142 | e.g. instead of "Missions", instructors may choose "Assessment" or any other suitable names. 143 | 144 | # Creating assessment 145 | 146 | ## Authoring assessment 147 | 148 | Take note that any changes made in the Assessment Creator will be accessible for learners to view after they have accepted the assessment. They will be present in the repository created for the learners. 149 | 150 | This includes all test cases and solutions to multiple-choice questions. If it is important that this information is not exposed, it is highly advised that they are not input into the Assessment Creator. 151 | 152 | ### Opening Assessment Creator 153 | 154 | 1. After logging in on the classrooms page, click on the "Create A New Assessment!" button. 155 | 2. This will bring you to the editor workspace. The following sections will explain how to edit assessments on this page. 156 | 157 | ### Editing starter code 158 | 159 | 1. The code editor on the left panel displays the starter code. This is the code that learners will see when they first accept the assessment. 160 | 2. Any changes you make as a teacher will be reflected in the starter code. 161 | 162 | ### Editing multiple choice question 163 | 164 | Take note that the solution will be available to the learner through their GitHub repository. 165 | 166 | 1. The website is only able to recognize multiple-choice questions if the starter code is written in a specific format. This format should include the prefix "MCQ", followed by a JSON object. An example is given below: 167 | 168 | ```json 169 | MCQ 170 | { 171 | "choices": 172 | [ 173 | { "option": "Alice", "hint":"Not this one" }, 174 | { "option": "Bob", "hint":"Not this one" }, 175 | { "option": "Charlie", "hint":"" } 176 | ], 177 | "answer": -1, 178 | "solution": 2 179 | } 180 | ``` 181 | 182 | The possible choices for the question should be contained in an array. This array should be populated with objects containing the following properties: 183 | 184 | - option: The contents of the choice. 185 | - hint: A message that will pop up upon clicking the choice. This can be left as an empty string. 186 | 187 | It is recommended that the "answer" is left as -1. This variable will be used to track the learners' answers. 188 | 189 | If a solution is not provided, all choices will be highlighted in red when selected. If a solution is provided, the choice will be highlighted in green when selected. The choices are zero-indexed. Therefore, the correct solution amongst the choices above is "Charlie". 190 | 191 | If you do not want to provide the solution with the question (since learners have access to their own GitHub repositories) the solution can be set to -1. 192 | 193 | 2. To view the question from your learner's point of view, click the toggle button in the control bar. If the view does not change, the JSON might be malformed.\ 194 | ![Text and Learner View](https://user-images.githubusercontent.com/47176493/122369178-8c3d4d00-cf90-11eb-9022-efcdcc1d4b1c.png) 195 | 196 | ### Editing assessment briefing and task description 197 | 198 | 1. Click on the text to open a markdown editor 199 | 2. Edit the text as necessary. 200 | 3. Clicking away from the editor will cause the text to render. 201 | 202 | ### Adding and deleting task 203 | 204 | 1. Click on the add button to add another task. This will add a task numbered greater than the current task by 1. 205 | 2. You can navigate between tasks with the Next and Previous buttons. 206 | 3. You can click on the delete button to get rid of a task. 207 | 208 | ### Writing test case 209 | 210 | Take note that any test cases will also appear in the learner's side of the website. 211 | 212 | ![Testcase example](https://user-images.githubusercontent.com/47176493/122352810-087c6400-cf82-11eb-8058-222d671229a6.png) 213 | 214 | 1. You may add a new test case by clicking on the "Add a new test case" button. You may edit the test program and the edited result. The actual result is generated by the website when the test case is ran. 215 | 2. You may run a test case by clicking the Play button on the right. You may also run all the test cases at once by running the program with the test cases tab open. 216 | 3. You may delete a test case by clicking the the X button on the right. 217 | 4. You may also edit the Test Prepend and Test Postpend. The Test Prepend will be appended in front of the learner's program, while the Test Postpend will be appended to end of the learner's program. You can use this to set up variables or define helper functions for your tests. 218 | 219 | ### Editing assessment metadata 220 | 221 | Currently, the Assessment Metadata only contains a single variable - the Source Version. 222 | 223 | The Source Version will dictate which capabilities and libraries the programs will have access to. Please follow this link for more details: . 224 | 225 | ### Saving changes 226 | 227 | 1. Click on the "Save" button. 228 | 2. If you are creating a new assessment, you will be prompted to name the new repository. 229 | 3. Click "Confirm" to continue. You can check corresponding GitHub repository to ascertain that the changes were saved. 230 | 231 | ### Using old XMLs 232 | 233 | There is currently no automated conversion from an XML-file to an assessment repository. Old XMLs need to be manually converted into assessment repositories, whether through the website interface or through committing to a GitHub repository. 234 | 235 | In order to accomplish this, you may copy-and-paste the relevant sections of the XML (such as the briefings and task descriptions) into the workspace, and save to GitHub. 236 | 237 | ## Publishing assessment 238 | 239 | ### Turning repository into template repository 240 | 241 | 1. Navigate to the GitHub page of the repository you would like to use as a template for your assessment. 242 | 2. Navigate to settings and tick the box for "Template repository". 243 | 244 | ### Creating GitHub Classroom assessment 245 | 246 | 1. In the GitHub Classroom page, navigate to your organization. 247 | 2. Click on "New assignment". 248 | 3. In the new page, copy down the repository prefix for use in the next section. This will be used to locate student repositories for this assessment. 249 | ![Setting repository prefix](https://user-images.githubusercontent.com/42378805/122539209-ed7d2300-d059-11eb-9dd1-8c417f8d3736.png) 250 | 4. Fill in the details for your organization. Make sure to use the [template repository](#creating-template-repositories) as the template repository for the new assessment under the Starter Code section. 251 | 5. After your assessment has been created, an invitation link to accept the assessment will be created. Copy down this link for use in the next section. This link can be found on the GitHub Classroom page of the assessment.\ 252 | ![Invitation Link](https://user-images.githubusercontent.com/47176493/122371718-a7a95780-cf92-11eb-93c9-fd73f37b52cb.png) 253 | 254 | ### Adding assessment to the Source Academy Course 255 | 256 | 1. Navigate to the course-info repository in your organization on GitHub. 257 | 2. Add an entry for the new assessment into the relevant category in the course-info.json file. 258 | For example, if this assessment belongs under "Missions", add it to the end of the "assessments:" array for that category. 259 | ![Add Entry](https://user-images.githubusercontent.com/42378805/122541401-2ddda080-d05c-11eb-9e19-072708acbe15.png) 260 | 261 | The entry should look something like this: 262 | 263 | ```json 264 | { 265 | "title": "insert-title-here", 266 | "openAt": "2020-12-01T00:00:00+08:00", 267 | "closeAt": "2021-12-31T23:59:59+08:00", 268 | "published": "yes", 269 | "coverImage": "insert-image-URL-here", 270 | "shortSummary": "insert-summary-here", 271 | "acceptLink": "paste-accept-link-here", 272 | "repoPrefix": "paste-repository-prefix-here" 273 | } 274 | ``` 275 | 276 | # Grading assessment 277 | 278 | We currrently do not have specific support for auto-testing assessments. Instructors will have to develop their own test scripts, download student submissions using GitHub Classroom, and communicate the results to learners. 279 | 280 | Downloading submissions requires the use of GitHub Classroom Assistant, which can be downloaded at https://classroom.github.com/assistant. 281 | 282 | A link to download repositories can be accessed from an assignment's page on GitHub Classroom:\ 283 | ![Download Repositories](https://user-images.githubusercontent.com/47176493/122371252-500aec00-cf92-11eb-8cd0-af32c379f22e.png) 284 | 285 | # Closing course 286 | 287 | After a course has ended, and you intend to teach it again, you may intend to reuse the same classroom. This would confer some benefits - such as being able to reuse the same course-info repository, as well as the same assignments (albeit after changing the due date). 288 | 289 | You may also leave the classroom as it is and create a new classroom organization, so that your learners would have access to their work. 290 | 291 | ## Removing learners and repositories 292 | 293 | If you intend to reuse the same classroom, it would be wise to remove all currently enrolled learners and their repositories. As this would cause them to lose access to their work, you should advise them to save their work - either by forking or downloading their repositories - before a deadline. 294 | 295 | After the deadline is reached, you can remove all members by navigating to People, selecting all members and removing them from the organization. **Please take care to uncheck yourself so that you are not also removed.** 296 | 297 | ![Removing all members](https://user-images.githubusercontent.com/47176493/122524160-63798e00-d04a-11eb-821e-42f8c2e63076.png) 298 | 299 | After all learners are removed, you would also have to remove all repositories (other than the course-info repository). 300 | 301 | While you could manually delete each repository through the GitHub interface, it is recommended that you delete them with a script. While we do not currently have any such scripts, we would like to direct you to this [thread](https://gist.github.com/mrkpatchaa/63720cbf744a2bf59a3e9cfe73fc33b0). 302 | 303 | Be careful not to delete the course-info repository, or to save a copy of its contents if you do delete it. 304 | -------------------------------------------------------------------------------- /educator/voting/README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | Instructors can setup a voting question for students to vote for some popular solutions of specific assessments using a ranked tierlist. 4 | 5 | ## Content 6 | 7 | - [Voting Workflow](#voting-workflow) 8 | - [Instructor](#instructor) 9 | - [Students](#students) 10 | - [Voting XML](#contest-voting-xml) 11 | - [Voting Guide](#voting-guide) 12 | - [Different Contest Types](#different-contest-types) 13 | - [Random Assignment of Entries](#random-assignment-of-entries) 14 | - [Valid vs Invalid Entries](#valid-vs-invalid-entries) 15 | - [Leaderboard](#leaderboard) 16 | ## Voting Workflow 17 | 18 | ### Instructor 19 | 20 | 1. Upload a contest.xml in ground control 21 | 22 | Note that the backend **does not anonymize** students' answers, hence students should submit a standardized function header without their names for anonymity. 23 | 2. Once the contest has ended, upload the contest-voting.xml in ground control 24 | 25 | The vote assignment will be generated at the point of time of upload of contest-voting.xml (this is a possible future improvement that can be made) 26 | 3. Students can vote once the contest voting assessment is open, and the rolling leaderboard will compute the scores 27 | 28 | The rolling leaderboard will compute the scores of each student based on votes recieved and number of tokens in the student's answer. More information can be found in [Leaderboard](#leaderboard). 29 | 30 | ### Students 31 | 32 | 1. Students access the side contents to vote for their favorite entries. 33 | Students can then execute the program and view the contest entries to vote for. 34 | Students vote by dragging and dropping the card corresponding to the entry they are voting for into the tierlist. 35 | ![image](https://github.com/source-academy/general/assets/122250318/12f69841-6e95-4510-b1a2-8da2229aba01) 36 | 37 | 38 | 2. Once the student finalises the submission, the drag-and-drop function is disabled and scores are submitted based on the tier the student has placed each entry in. 39 | 40 | ## Contest Voting XML 41 | 42 | Similar to the creating an [assessment xml](../assessment/README.md) for programming and mcq questions, except that except that you need to declare the [PROBLEM](../assessment/README.md#problem) type as “voting” and include a VOTING tag ``. 43 | 44 | ### VOTING Attributes 45 | 46 | | attribute | details | 47 | | --------- | ------- | 48 | | assessment_number | The assessment number of the **contest** (i.e. If a contest was uploaded with the number "C4", the assessment_number will be "C4"). Required. | 49 | 50 | ### Example of a contest voting xml: 51 | 52 | ```xml 53 | 54 | 55 | 56 | 59 | 65 | Textbook Chapter 1 66 | 67 | 68 | Now is the time to rank the most beautiful runes made by your peers in a tierlist! 69 | 70 | You will be randomly assigned 10 runes to rank, from S to D tier! 71 | 72 | 73 | 74 | 75 | 76 | You can now vote on the most beautiful runes made by your fellow students! 77 | 78 | 79 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | ``` 93 | 94 | ## Voting Guide 95 | 96 | ### Different Contest Types 97 | 98 | Students can vote on contests involving images (runes/curves) or sounds. The relevant modules will be automatically imported from Source Academy in the assessment. 99 | 100 | ### Random Assignment of Entries 101 | 102 | Up to 10 entries from the contest entry bank will be randomly assigned to each student to vote on. 103 | 104 | ## Leaderboard 105 | 106 | When the contest is ongoing, instructors will be able to view the rolling leaderboard by opening the contest voting assessment in their own account and navigating to the leaderboard pane. 107 | ![image](https://github.com/source-academy/general/assets/122250318/86775e8e-982f-44fb-80bd-d7372807bcbd) 108 | After the contest has finished, both instructors and students will be able to view the final leaderboard by opening the contest voting assessment in their own account and navigating to the leaderboard pane. 109 | ![image](https://github.com/source-academy/general/assets/122250318/88d43007-949e-4d68-ab8e-d2b33d1e90c9) 110 | -------------------------------------------------------------------------------- /learner/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | label: SICP JS 3 | --- 4 | 5 | # Resources for learners who use SICP JS 6 | 7 | The learners in the Source Academy community might find the following resources useful. 8 | 9 | - [Interactive SICP JS](https://sourceacademy.org/sicpjs): online version of the textbook *Structure and Interpretation of Computer Programs, JavaScript Edition* 10 | - [SICP JS in print](https://mitpress.mit.edu/books/structure-and-interpretation-computer-programs-1): print version of *Structure and Interpretation of Computer Programs, JavaScript Edition*, published by MIT Press 11 | - [SICP JS in PDF](https://sicp.sourceacademy.org/sicpjs.pdf): latest PDF, subject to a [CC NC-BY-SA license](https://creativecommons.org/licenses/by-nc-sa/4.0/) 12 | - [Programs of SICP JS](https://sicp.sourceacademy.org/sicpjs.zip): all programs of the book, in a zip file 13 | - [Source](https://docs.sourceacademy.org): Source languages used in the book (sublanguages of JavaScript) 14 | - [SICP JS on github](https://github.com/source-academy/sicp): repository for typesetting our own copy and contributing 15 | - [Videos](https://www.youtube.com/@sourceacademy1027): Youtube channel on Source Academy and its tools 16 | 17 | Currently, learners have the following options. If you take a course based on SICP JS, check with your instructor which option applies to the course: 18 | 19 | - [Learn with SICP JS without Source Academy](../package/README.md) 20 | - [Learn with Source Academy](../vanilla/README.md) (public site) 21 | - [Learn with Source Academy @ X](x/README.md) 22 | 23 | # Resources for educators who use SICP JS 24 | 25 | The educators in the Source Academy community might find the following resources useful. In addition, the NUS instructor team provides educator material including homework assignments, exams of previous years with solutions, and weekly classroom exercises. Email [sourceacademy@nus.edu.sg](mailto:sourceacademy@comp.nus.edu.sg) to get access to these resources. 26 | 27 | Educators have the following options to work with [SICP JS](https://sourceacademy.org/sicpjs/): 28 | - Not use Source Academy: You can use SICP JS with the IDE of your choice; [see here](../package/README.md) for more information 29 | - Use the public version of the Source Academy; [see here](../vanilla/README.md) how [Source Academy](https://sourceacademy.org/) supports your course 30 | - Source Academy @ NUS: An extension of Source Academy; [go here](https://sourceacademy.nus.edu.sg) to create your account and start your course 31 | - Deploy your own Source Academy @ X; [see here](../deployment/README.md) how to do that 32 | 33 | Educators who have used the original Scheme-based SICP book may appreciate our [Scheme-JavaScript Comparison Edition](https://sicp.sourceacademy.org), where SICP and SICP JS can be viewed side-by-side. 34 | 35 | ## Resources for educators who use [Source Academy @ NUS](https://sourceacademy.nus.edu.sg/) 36 | 37 | - Register as instructor: send an email to [source.academy.nus@gmail.com](mailto:source.academy.nus@gmail.com) 38 | - [Guide for authoring and uploading assessments](assessment/README.md): homework submissions stored on the **Source Academy @ NUS** or any other Source Academy server, graded by you and your assistants or auto-graded 39 | - [Guide for managing contest voting](voting/README.md): setup for students to vote for the most popular submissions in a contest 40 | - [Guide for setting up a Source Academy game](game/README.md): game provides context for homework assignments 41 | 42 | ## Courses using SICP JS and Source Academy 43 | 44 | - [CS1101S at NUS](https://www.comp.nus.edu.sg/~cs1101s): CS1 course for Computer Science majors at National University of Singapore, using SICP JS since 2012 45 | - [A Taste of Programming with SICP JS](https://about.sourceacademy.org/IAP/): MIT course during Independent Activity Period, January 18-28, 2022 46 | - [Program construction and data structures](https://www.uu.se/utbildning/kursplan?query=47706): CS1 course for Computer Science majors at Uppsala University in Sweden, using SICP JS since 2022 47 | 48 | -------------------------------------------------------------------------------- /learner/github/README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | This guide instructs learners how to make use of the Source Academy interface to complete their homework. 4 | 5 | ## Content 6 | 7 | - [Entering into a GitHub Classroom organization](#entering-into-a-github-classroom-organization) 8 | - [Viewing and accepting assessments](#viewing-and-accepting-assessments) 9 | - [Attempting and submitting assessments](#attempting-and-submitting-assessments) 10 | - [Finishing a course](#finishing-a-course) 11 | 12 | ### Entering into a GitHub Classroom organization 13 | 14 | 1. Provide your instructor with your GitHub username. They must invite you to join the organization. 15 | 2. Once they have sent you an invite, check your email and accept the invite to join the organization. 16 | 17 | ### Viewing and accepting assessments 18 | 19 | 1. Navigate to the Source Academy website at and navigate to Classrooms. 20 | 2. Log into your GitHub account (this must be the same one that is a member of the classroom/organization). 21 | 3. Browse the "Select Course" dropdown menu and select the course that has the assessment. 22 | 4. The assessments are displayed after the previous step. Navigate to the assessment that you want to attempt. 23 | 5. You need to "accept" an assessment before you can attempt it. The "Accept" button on the card lets you do that, by taking you to a page on GitHub.\ 24 | ![Click on Accept Button](https://user-images.githubusercontent.com/47176493/122347381-8ccbe880-cf7c-11eb-8d26-a333e4630827.png) 25 | 26 | 6. Once on the page, click on "Accept this assignment" and GitHub will create a new repository for you.  27 | ![Accept Assignment](https://user-images.githubusercontent.com/47176493/122345872-eb906280-cf7a-11eb-8291-da408058156c.png) 28 | 29 | If your acceptance is successful, the following page will appear:\ 30 | ![After Accepting Assignment](https://user-images.githubusercontent.com/47176493/122346036-1d092e00-cf7b-11eb-8fce-b92b2a77fe89.png) 31 | 32 | 7. After you haved already accepted the assessment, the text on the cards will be "Open" instead. You may click on this button to begin or continue attempting the assessment.\ 33 | ![Click on Open Button](https://user-images.githubusercontent.com/47176493/122347450-9ead8b80-cf7c-11eb-8108-bca0b2532ab9.png) 34 | 35 | 8. Follow instructions to clone the assessment and it should now be available to attempt on Source Academy Classrooms. 36 | 37 | ### Attempting and submitting assessments 38 | 39 | 1. For programming questions, you can write your answers in the code editor on the left.\ 40 | ![Programming Question](https://user-images.githubusercontent.com/47176493/122347797-019f2280-cf7d-11eb-864f-b37bef2569c1.png) 41 | 42 | For multiple-choice questions, you can click on the answer. Take note that depending on the question's settings, the correct answer might still be highlighted in red.\ 43 | ![MCQ](https://user-images.githubusercontent.com/47176493/122347847-0ebc1180-cf7d-11eb-91dd-8b0fc1157bb6.png) 44 | 45 | 2. Some questions have test cases that you can view through the test case tab on the right. To run individual test cases, you may click on them. Otherwise to run all the test cases, you can run the program while the test case tab is selected. 46 | 3. When you are satisfied with your answers, remember to click on "Save" to save your changes. 47 | 4. You can check the repository on GitHub to ensure that your changes are carried over. **Note that after the submission date, any new commits will not be reflected in the Classroom assessment.** 48 | 49 | ### Finishing a course 50 | 51 | After a course has ended, you might want to save a copy of your work if you intend to refer back to it in the future. As the work repositories belong to the classroom organization, you may lose access to them if the organization is deleted, or if you are removed from the organization (whether by choice or by your instructor). 52 | 53 | In order to do this, you could fork any of your homework repositories, or download a copy of the code. 54 | ![How to save work](https://user-images.githubusercontent.com/47176493/122519182-bfd9af00-d044-11eb-9942-b2c39f208dea.png) 55 | 56 | You may also choose to leave the organization (so that the course will no longer show up while using the Source Academy website). In order to do so, navigate to "Your organizations" on GitHub and leave the organization. 57 | -------------------------------------------------------------------------------- /learner/x/README.md: -------------------------------------------------------------------------------- 1 | # Source Academy @ X 2 | 3 | The public [Source Academy site](https://sourceacademy.org) lets learners connect to Google Drive and Github to store your programs. 4 | 5 | [Source Academy @ NUS](https://sourceacademy.nus.edu.sg) is an extension of the public [Source Academy site](https://sourceacademy.org) that allows educators to set up and manage a course and enrol learners and staff. Staff can set up *Assessments*, learners can submit assessments, and staff can grade assessments manually or set up automated grading using test cases. Source Academy @ NUS also features *Achievements* that give learners continuous feedback on their performance in Assessments. Educators can set up a graphic-novel style game that provides the context for themed Assessments and release Chapters of the game as their course unfolds. 6 | 7 | Educators can consult [Resources for educators](../../educator/README.md) for details on how to set up a course in Source Academy @ X. 8 | -------------------------------------------------------------------------------- /package/README.md: -------------------------------------------------------------------------------- 1 | # Using SICP JS with the IDE of your choice 2 | 3 | ## NPM package `sicp` 4 | 5 | The [Node.js NPM package `sicp`](https://www.npmjs.com/package/sicp) provides all predeclared functions and constants assumed by the [SICP JS textbook](https://sourceacademy.org/sicpjs). Consult the [README](https://www.npmjs.com/package/sicp) of the NPM package `sicp` for installation instructions. 6 | The functions and constants are [documented here](https://docs.sourceacademy.org/source_4/global.html). 7 | 8 | ## Programs of SICP JS 9 | 10 | The programs of SICP JS are available [as a zip file](https://sicp.sourceacademy.org/sicpjs.zip). 11 | 12 | ## Caveat 13 | 14 | SICP JS relies on a JavaScript feature called "proper tail calls". This feature is specified by the JavaScript standards since 2015, but unfortunately as of 2021, most web browsers do not comply with this aspect of the standard. Node.js does not comply, either, and as a result, some programs in SICP JS will not scale when using the package `sicp` in Node.js in the way they should. This will not affect learners in a major way. 15 | 16 | The [Source Academy](https://sourceacademy.org) avoids the problem by transpiling the SICP JS sublanguage of JavaScript to JavaScript such that the resulting implementation performs proper tail calls regardless whether the underlying JavaScript implemementation has proper tail calls. 17 | -------------------------------------------------------------------------------- /research/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | label: Researchers 3 | --- 4 | 5 | # Resources for researchers 6 | 7 | The Source Academy and SICP JS are used for educational research. Below you find some resources. 8 | 9 | ## Publications 10 | 11 | - [Visualizing Environments of Modern Scripting Languages](https://www.comp.nus.edu.sg/~henz/publications/#csedu2023.abstract). Kaian Cai, Martin Henz, Kok-Lim Low, Xing Yu Ng, Jing Ren Soh, Kyn-Han Tang, and Kar Wi Toh. Proceedings of the 2023 Proceedings of the 2023 International Conference on Computer Supported Education (CSEDU 2023), Prague, Czech Republic. April 2023. 12 | - [Community-driven Course and Tool Development for CS1](https://www.comp.nus.edu.sg/~henz/publications/#sigcsets2023.abstract). Boyd Anderson, Martin Henz, Kok-Lim Low. Proceedings of the 2023 ACM SIGCSE Technical Symposium on Computer Science Education (SIGCSE TS 2023), ACM, New York, NY, United States. March 2023. 13 | - [Teachable Moments in Functional Audio Processing](https://www.comp.nus.edu.sg/~henz/publications/index.html#splasheteachable2021.abstract). Martin Henz, Shang-Hui Koh, Samyukta Sounderraman. Proceedings of the 2021 ACM SIGPLAN International SPLASH-E Symposium (SPLASH-E '21), ACM, New York, NY, United States. 20 Oct 2021. 14 | - [Shrinking JavaScript for CS1](https://www.comp.nus.edu.sg/~henz/publications/index.html#splasheshrinking2021.abstract). Boyd Anderson, Martin Henz, Kok-Lim Low, Daryl Tan. Proceedings of the 2021 ACM SIGPLAN International SPLASH-E Symposium (SPLASH-E '21), ACM, New York, NY, United States. 20 Oct 2021. 15 | - [A Stepper for a Functional JavaScript Sublanguage](https://www.comp.nus.edu.sg/~henz/publications/index.html#splashestepper2021.abstract). Martin Henz, Thomas Tan, Zachary Chua, Peter Jung, Yee-Jian Tan, Xinyi Zhang, Jingjing Zhao. Proceedings of the 2021 ACM SIGPLAN International SPLASH-E Symposium (SPLASH-E '21), ACM, New York, NY, United States. 20 Oct 2021. 16 | - [Ruggedizing CS1 Robotics: Tools and Approaches for Online Teaching](https://www.comp.nus.edu.sg/~henz/publications/index.html#splasheruggedizing2021.abstract). Boyd Anderson, Martin Henz, Hao-Wei Tee. Proceedings of the 2021 ACM SIGPLAN International SPLASH-E Symposium (SPLASH-E '21), ACM, New York, NY, United States. 20 Oct 2021. 17 | 18 | ## Invited talks and demos 19 | 20 | - [Source Academy: A Web-based Environment for Learning Programming with SICP](https://sigcse2023.sigcse.org/details/sigcse-ts-2023-demos/6/Source-Academy-A-Web-based-Environment-for-Learning-Programming-with-SICP) by Martin Henz. [SIGCSE TS 2023](). March 16, 2023. Available: [demo description](https://www.comp.nus.edu.sg/~henz/publications/pdf/SIGCSETSDEMO.pdf), [video](https://www.youtube.com/watch?v=s_UPhAT25fo) 21 | 22 | - Xtreme Shrinking of JS for Teaching by Martin Henz. [XtremeJS 2022](https://xtremejs.dev/2022/schedule/). December 13, 2022. Available: [slides with links](https://www.comp.nus.edu.sg/~henz/publications/pdf/Xtreme_Shrinking.pdf), [video](https://www.youtube.com/watch?v=GGnZoB3Bekg) 23 | 24 | - Meaningful online learning experiences with Source Academy by Martin Henz. [Experiential Learning Seminar Series](https://www.cetl.hku.hk/elseminar22/), Centre for the Enhancement of Teaching and Learning, University of Hong Kong. June 2, 2022. Available: [slides](https://www.comp.nus.edu.sg/~henz/publications/pdf/meaningful_online_learning.pdf) 25 | 26 | - [Shrinking JavaScript for an SICP-based First-Year Course](https://www.csail.mit.edu/event/martin-henz-shrinking-javascript-sicp-based-first-year-course) by Martin Henz. MIT CSAIL Seminar. March 7, 2022. Available: [slides](https://www.comp.nus.edu.sg/~henz/publications/pdf/Shrinking_JavaScript_Slides.pdf), [video](https://youtu.be/NnuQfEekKGg) 27 | 28 | - [SICP JS: Ketchup on Caviar?](https://www.comp.nus.edu.sg/~henz/publications/index.html#ketchup2020.abstract) by Martin Henz. Keynote. Proceedings of the 2020 Scheme and Functional Programming Workshop at the 25th ACM SIGPLAN International Conference on Functional Programming, August 2020. 29 | 30 | ## Technical reports 31 | 32 | ### Specification of Source Languages 33 | 34 | - [Specification of Source §1](https://docs.sourceacademy.org/source_1.pdf) 35 | - [Specification of Source §2](https://docs.sourceacademy.org/source_2.pdf) 36 | - [Specification of Source §3](https://docs.sourceacademy.org/source_3.pdf) 37 | - [Specification of Source §4](https://docs.sourceacademy.org/source_4.pdf) 38 | 39 | - [Specification of Source §1 Lazy](https://docs.sourceacademy.org/source_1_lazy.pdf) 40 | - [Specification of Source §1 WebAssembly](https://docs.sourceacademy.org/source_1_wasm.pdf) 41 | - [Specification of Source §2 Lazy](https://docs.sourceacademy.org/source_2_lazy.pdf) 42 | - [Specification of Source §3 Non-Det](https://docs.sourceacademy.org/source_3_nondet.pdf) 43 | - [Specification of Source §3 Concurrent](https://docs.sourceacademy.org/source_3_concurrent.pdf) 44 | - [Specification of Source §4 GPU](https://docs.sourceacademy.org/source_4_gpu.pdf) 45 | 46 | ### Other technical reports 47 | 48 | - [Specification of Source §1 Infinite Loop Detection](https://docs.sourceacademy.org/source_1_infinite_loop_detection.pdf) 49 | - [Specification of Source §2 Stepper](https://docs.sourceacademy.org/source_2_stepper.pdf) 50 | - [Specification of Source §3 Type Inference](https://docs.sourceacademy.org/source_3_type_inference.pdf) 51 | -------------------------------------------------------------------------------- /vanilla/README.md: -------------------------------------------------------------------------------- 1 | # Using Source Academy in an SICP-JS-based course 2 | 3 | The Source Academy is designed for learners who use the textbook [Structure and Interpretation of Computer Programs, JavaScript Adaptation](https://sourceacademy.org/sicpjs/). [This link](https://sourceacademy.org/) provides access to the Source Academy. 4 | 5 | ## Language selection 6 | 7 | The Playground allows you to choose one of four [Source languages](https://docs.sourceacademy.org). The Source languages are sublanguages of JavaScript, designed for the chapters of SICP JS. The language Source §1 has just enough features for the content of Chapter 1 of SICP JS, Source §2 has jsut enough features for the first two chapters, and so on. 8 | 9 | Screenshot 2021-05-20 at 9 51 16 AM 10 | 11 | ## Language tools 12 | 13 | ### Stepper 14 | 15 | ### Data visualizer 16 | 17 | ### Environment visualizer 18 | 19 | ## Programming environment 20 | 21 | ### Modules 22 | 23 | ### Share links 24 | 25 | ### Collaborative sessions 26 | 27 | ### Program editor 28 | 29 | ### Github and Google Drive integration 30 | --------------------------------------------------------------------------------