├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitlab-ci.yml ├── .vs ├── ProjectSettings.json └── slnx.sqlite ├── Apps ├── CurrentWeatherAppDemo.mlapp ├── CurrentWeatherAppStart.mlapp └── WeatherDisplay.mlapp ├── CONTRIBUTING.md ├── FunctionLibrary ├── .gitkeep ├── CheckPythonVersion.mlx └── helloworld.py ├── Images ├── AddCallbackFromContextMenu.mlx ├── AddCallbackInComponentBrowser.mlx ├── AddFunction.mlx ├── AddMultipleComponentsToApp.mlx ├── AddOnsIcon.png ├── AddProperty.mlx ├── EndIcon.png ├── MouseThoughtBubble.png ├── NatickTempPress.png ├── NatickWind.png ├── OpenInFX.png ├── OpenInMO.png ├── RGBTurkeys.png ├── RunPythonLiveTask.png ├── SeaSurfaceTemps.png ├── TestedWith.json ├── WeatherDashboard.png ├── WeatherStruct.png └── windTokyo.gif ├── InstructorResources └── Solutions │ ├── CheckingTheWeatherSoln.mlx │ ├── CreateCurrentWeatherAppSoln.mlx │ └── UsingMATLABwithPythonSoln.mlx ├── LICENSE.md ├── MATLABwithPython.prj ├── MainMenu.mlx ├── README.md ├── README.mlx ├── SECURITY.md ├── Scripts ├── CheckingTheWeather.mlx ├── CreateCurrentWeatherApp.mlx ├── UsingMATLABwithPython.mlx └── checkcurrentweather.py ├── SoftwareTests ├── CheckTestResults.m ├── CreateBadge.m ├── FunctionTests.m ├── OrigSmokeTests.m ├── PostFiles │ ├── PostCheckingTheWeather.m │ ├── PostCheckingTheWeatherSoln.m │ ├── PostCreateCurrentWeatherApp.m │ ├── PostCreateCurrentWeatherAppSoln.m │ ├── PostUsingMATLABwithPython.m │ └── PostUsingMATLABwithPythonSoln.m ├── PostSmokeTest.m ├── PreFiles │ ├── PreCheckingTheWeather.m │ ├── PreCheckingTheWeatherSoln.m │ ├── PreCreateCurrentWeatherApp.m │ ├── PreCreateCurrentWeatherAppSoln.m │ ├── PreUsingMATLABwithPython.m │ ├── PreUsingMATLABwithPythonSoln.m │ ├── Response.json │ └── ResponseOneCall.json ├── Response.json ├── ResponseOneCall.json ├── ResponseOneCallOneLine.json ├── RunAllTests.m ├── SmokeTests.m ├── SolnSmokeTests.m ├── TestResults_R2023a.txt └── TestResults_R2024a.txt ├── Utilities ├── OldVersions │ ├── CheckingTheWeatherOld.mlx │ └── UsingMATLABwithPythonOld.mlx ├── ProjectShutdown.m ├── ProjectStartupApp.m └── SurveyLinks.mat └── resources └── project ├── 2zjcQkVJSJ_AwC9M8R9BTSESRzc ├── QEd0x6jBcKf03RgXQ3y07QAWBCsd.xml ├── QEd0x6jBcKf03RgXQ3y07QAWBCsp.xml ├── _kanDHLwZvrSM1wrb2rL3R-TtpAd.xml ├── _kanDHLwZvrSM1wrb2rL3R-TtpAp.xml ├── b4fK1nwNVcMFfH2HWk_9bHC2cXcd.xml └── b4fK1nwNVcMFfH2HWk_9bHC2cXcp.xml ├── 6xhH2l9GP9loT6TdFn_Mo65sDHg ├── P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml └── P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml ├── BT5hWoz-UTefONdqForZyI91O8Y ├── -Yp4iI7AkN0RXWsqH_qBv8BSoUsd.xml ├── -Yp4iI7AkN0RXWsqH_qBv8BSoUsp.xml ├── 5wkpcXVsAhrdVuZJuRCjlxSek_Yd.xml ├── 5wkpcXVsAhrdVuZJuRCjlxSek_Yp.xml ├── 897K1ZIAIxWZa69h7rzaFEkJJ1Yd.xml ├── 897K1ZIAIxWZa69h7rzaFEkJJ1Yp.xml ├── LUM1KVG-kpiMYV7i1xDItZmUkVQd.xml ├── LUM1KVG-kpiMYV7i1xDItZmUkVQp.xml ├── SGHsdnqYqyGyYGQP-0wqh6AyERAd.xml ├── SGHsdnqYqyGyYGQP-0wqh6AyERAp.xml ├── TzEa1ML1Hz49sPNQX5JM6EE413Qd.xml ├── TzEa1ML1Hz49sPNQX5JM6EE413Qp.xml ├── Ur1esh7xN9L6aqDUKBE31DKE1Qod.xml ├── Ur1esh7xN9L6aqDUKBE31DKE1Qop.xml ├── VnvWkijFxdp8LV3ck_Qpq9eyOpMd.xml ├── VnvWkijFxdp8LV3ck_Qpq9eyOpMp.xml ├── WNBzWWmVwu8nwCU7p01ZJtQ5j-od.xml ├── WNBzWWmVwu8nwCU7p01ZJtQ5j-op.xml ├── gK0bzvM8fEYFwItc078tqn4EOmId.xml ├── gK0bzvM8fEYFwItc078tqn4EOmIp.xml ├── h026LEbG6ImfsgAII1WcSM9Hnnod.xml ├── h026LEbG6ImfsgAII1WcSM9Hnnop.xml ├── nA_28eBnx5NCFw_vQVWFh5ohqUAd.xml ├── nA_28eBnx5NCFw_vQVWFh5ohqUAp.xml ├── w234j28OzyIgK86-1WWW6oJ1rp4d.xml ├── w234j28OzyIgK86-1WWW6oJ1rp4p.xml ├── xH29tmOwPG1ix8h2YNwMHPQ_-ukd.xml └── xH29tmOwPG1ix8h2YNwMHPQ_-ukp.xml ├── BjxNC43HIPP8KZwg_cceb68ikkA ├── AHoLGOV6JxAa3mDfXPOye2W3psUd.xml ├── AHoLGOV6JxAa3mDfXPOye2W3psUp.xml ├── NvNsziUvXU2FO5oXU12jeMmASEwd.xml ├── NvNsziUvXU2FO5oXU12jeMmASEwp.xml ├── dxW0rLxFMXm0cpQGCSkWQRi2YRsd.xml └── dxW0rLxFMXm0cpQGCSkWQRi2YRsp.xml ├── EEtUlUb-dLAdf0KpMVivaUlztwA ├── -upqjogKesBp3DwJRlG6KjrKvd4d.xml ├── -upqjogKesBp3DwJRlG6KjrKvd4p.xml ├── 2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml ├── 2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml ├── DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml ├── DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml ├── JzO7EW4RnUYzi9OV7qh3x-wX4z8d.xml ├── JzO7EW4RnUYzi9OV7qh3x-wX4z8p.xml ├── Pq7gqYnkFyhKab7XB8O0iwQTIP0d.xml ├── Pq7gqYnkFyhKab7XB8O0iwQTIP0p.xml ├── _8KD0FwxV6biv7mEQTGecP1TTPgd.xml ├── _8KD0FwxV6biv7mEQTGecP1TTPgp.xml ├── cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml ├── cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml ├── dzjyExK2OLpL1YhePZIjY4vjrpsd.xml ├── dzjyExK2OLpL1YhePZIjY4vjrpsp.xml ├── e7wCov_BYJUY6VsFZYx5ab3064gd.xml ├── e7wCov_BYJUY6VsFZYx5ab3064gp.xml ├── ikoU0GqEAVreEIpyvUR8mCIaiqUd.xml ├── ikoU0GqEAVreEIpyvUR8mCIaiqUp.xml ├── lMJoqU1GA86jWAvX6adHL2EbMzMd.xml ├── lMJoqU1GA86jWAvX6adHL2EbMzMp.xml ├── nBednXcpm1PUS8qxyRkFXdab-P4d.xml └── nBednXcpm1PUS8qxyRkFXdab-P4p.xml ├── HoHDHQ_WvHAAKj5aJOrvrg_vpt8 ├── xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml └── xXlmKuOQ7YT_G1elNhbKQIUqSRMp.xml ├── KAXfQgCar2Yb8zOxgvf9hdmLP1E ├── jYpi1Pu6k-AfWEJrahCTREe7wz0d.xml ├── jYpi1Pu6k-AfWEJrahCTREe7wz0p.xml ├── xcK8fO1pjra5DR0jot5vrzlBV84d.xml └── xcK8fO1pjra5DR0jot5vrzlBV84p.xml ├── NjSPEMsIuLUyIpr2u1Js5bVPsOs ├── 2kj09UetkV_lru3gvSPXnY6-nM4d.xml ├── 2kj09UetkV_lru3gvSPXnY6-nM4p.xml ├── KKyDJtbdIBOlaeHmIZd5VX6vqx8d.xml ├── KKyDJtbdIBOlaeHmIZd5VX6vqx8p.xml ├── QWNDYJD5mGW1bWYvPx9DtKnxzw4d.xml ├── QWNDYJD5mGW1bWYvPx9DtKnxzw4p.xml ├── R1RggVhA72agIvELiuhWPRS8F0Id.xml ├── R1RggVhA72agIvELiuhWPRS8F0Ip.xml ├── aEHSZBIY-yve10yGis12Zr5DLZod.xml ├── aEHSZBIY-yve10yGis12Zr5DLZop.xml ├── j4xwF_j8iFTVayUMfxLgMnTbencd.xml ├── j4xwF_j8iFTVayUMfxLgMnTbencp.xml ├── r8LR4nLmg9ai3oHrW1r_-KocQzkd.xml └── r8LR4nLmg9ai3oHrW1r_-KocQzkp.xml ├── Project.xml ├── ZN2RlSIbyWXhOxbxxI4hOawbMD4 ├── EyDhXb-HjEIhAYfuSMUxquCH4aYd.xml ├── EyDhXb-HjEIhAYfuSMUxquCH4aYp.xml ├── d1u4eIKNgMuS21WRxXrD0UScuR8d.xml ├── d1u4eIKNgMuS21WRxXrD0UScuR8p.xml ├── gjXMbSOzqQJbg7H7bMF0OVGji80d.xml ├── gjXMbSOzqQJbg7H7bMF0OVGji80p.xml ├── p5HYYVUpTuYgZwnT8QkkzaoJraUd.xml ├── p5HYYVUpTuYgZwnT8QkkzaoJraUp.xml ├── q4FWbcu8zEbneDjWzNwfvfvjQNAd.xml ├── q4FWbcu8zEbneDjWzNwfvfvjQNAp.xml ├── s-04wUzHjOhlMa1CW_zpJwm8iDMd.xml └── s-04wUzHjOhlMa1CW_zpJwm8iDMp.xml ├── ZdVxxv9BsNz7MGUxtEc6Pq3qh1M ├── IeTljmmsHd59nip38CQ5y5dOQnQd.xml ├── IeTljmmsHd59nip38CQ5y5dOQnQp.xml ├── QOpe-1pctdftDIjwQLRdjOUZW44d.xml ├── QOpe-1pctdftDIjwQLRdjOUZW44p.xml ├── bzMXcEpQelehv3qzHYr9ceCGgIod.xml ├── bzMXcEpQelehv3qzHYr9ceCGgIop.xml ├── hy3T897OVbl4TCaWFBnKRKDU0M8d.xml └── hy3T897OVbl4TCaWFBnKRKDU0M8p.xml ├── fjRQtWiSIy7hIlj-Kmk87M7s21k ├── NjSPEMsIuLUyIpr2u1Js5bVPsOsd.xml └── NjSPEMsIuLUyIpr2u1Js5bVPsOsp.xml ├── iMwdHOXOBiBXhnA_li8gtEJVTjc ├── RMvf4mEDuznAOqU6SKNmIWErfxgd.xml ├── RMvf4mEDuznAOqU6SKNmIWErfxgp.xml ├── ZTr3GAe6p03ZVs2FdKKE0JsiFMQd.xml ├── ZTr3GAe6p03ZVs2FdKKE0JsiFMQp.xml ├── uIbyU9dPEHKvxjdwx5pD9PDDCZYd.xml └── uIbyU9dPEHKvxjdwx5pD9PDDCZYp.xml ├── qaw0eS1zuuY1ar9TdPn1GMfrjbQ ├── 2zjcQkVJSJ_AwC9M8R9BTSESRzcd.xml ├── 2zjcQkVJSJ_AwC9M8R9BTSESRzcp.xml ├── BT5hWoz-UTefONdqForZyI91O8Yd.xml ├── BT5hWoz-UTefONdqForZyI91O8Yp.xml ├── BjxNC43HIPP8KZwg_cceb68ikkAd.xml ├── BjxNC43HIPP8KZwg_cceb68ikkAp.xml ├── KocSmEw1PpelhlG7ZNeMUdHVtywd.xml ├── KocSmEw1PpelhlG7ZNeMUdHVtywp.xml ├── QMJD9OLFzxcTTbPOoh-ahQ4zTRUd.xml ├── QMJD9OLFzxcTTbPOoh-ahQ4zTRUp.xml ├── R0IsxKENiOKovWZXASFjrmpbBCYd.xml ├── R0IsxKENiOKovWZXASFjrmpbBCYp.xml ├── ZN2RlSIbyWXhOxbxxI4hOawbMD4d.xml ├── ZN2RlSIbyWXhOxbxxI4hOawbMD4p.xml ├── ZdVxxv9BsNz7MGUxtEc6Pq3qh1Md.xml ├── ZdVxxv9BsNz7MGUxtEc6Pq3qh1Mp.xml ├── iMwdHOXOBiBXhnA_li8gtEJVTjcd.xml ├── iMwdHOXOBiBXhnA_li8gtEJVTjcp.xml ├── rh0jHbNfmojECiiHH7BQHmZTsWkd.xml ├── rh0jHbNfmojECiiHH7BQHmZTsWkp.xml ├── rnpMu7jn2QWt_rQcz8FJ-MxGzVId.xml ├── rnpMu7jn2QWt_rQcz8FJ-MxGzVIp.xml ├── trBOSMFt-ZFz0tI8PrpBhVjGM5Md.xml └── trBOSMFt-ZFz0tI8PrpBhVjGM5Mp.xml ├── root ├── 6x1BhZX_fLnKpcwqra0qFwv1jIgp.xml ├── 6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml ├── EEtUlUb-dLAdf0KpMVivaUlztwAp.xml ├── GiiBklLgTxteCEmomM8RCvWT0nQd.xml ├── GiiBklLgTxteCEmomM8RCvWT0nQp.xml ├── HoHDHQ_WvHAAKj5aJOrvrg_vpt8p.xml ├── KAXfQgCar2Yb8zOxgvf9hdmLP1Ep.xml ├── NmGqIpAwUJcXFyLjFAGnU9uyN5Yp.xml ├── WZRuNzqc-Db7NcQAZO8Y-R8U9ccp.xml ├── fjRQtWiSIy7hIlj-Kmk87M7s21kp.xml └── qaw0eS1zuuY1ar9TdPn1GMfrjbQp.xml ├── rootp.xml ├── uuid-0192afd8-7310-46b8-ad07-aacb330fc399.xml └── uuid-366ca619-578a-4bc0-8012-bfa62d28c37f.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | *.fig binary 2 | *.mat binary 3 | *.mdl binary diff merge=mlAutoMerge 4 | *.mdlp binary 5 | *.mexa64 binary 6 | *.mexw64 binary 7 | *.mexmaci64 binary 8 | *.mlapp binary linguist-language=MATLAB 9 | *.mldatx binary 10 | *.mlproj binary 11 | *.mlx binary merge=mlAutoMerge linguist-language=MATLAB 12 | *.p binary 13 | *.sfx binary 14 | *.sldd binary 15 | *.slreqx binary merge=mlAutoMerge 16 | *.slmx binary merge=mlAutoMerge 17 | *.sltx binary 18 | *.slxc binary 19 | *.slx binary merge=mlAutoMerge linguist-language=Simulink 20 | *.slxp binary 21 | 22 | ## Other common binary file types 23 | *.docx binary 24 | *.exe binary 25 | *.jpg binary 26 | *.pdf binary 27 | *.png binary 28 | *.xlsx binary 29 | 30 | # Ignore HTML 31 | 32 | *.html linguist-detectable=false 33 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: MATLAB Build 2 | 3 | # Controls when the action will run. 4 | on: 5 | push: 6 | branches: [ release ] 7 | pull_request: 8 | branches: [ release ] 9 | workflow_dispatch: 10 | 11 | # Add permission to write GitHub pages 12 | permissions: 13 | contents: write 14 | pages: write 15 | id-token: write 16 | 17 | jobs: 18 | test: 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | MATLABVersion: [R2024a,R2024b] 23 | runs-on: ubuntu-latest 24 | steps: 25 | # Checks-out your repository 26 | - uses: actions/checkout@v4 27 | 28 | # Sets up a display server 29 | - name: Start display server 30 | if: ${{ always() }} 31 | run: | 32 | sudo apt-get install xvfb 33 | Xvfb :99 & 34 | echo "DISPLAY=:99" >> $GITHUB_ENV 35 | 36 | # Sets up MATLAB 37 | - name: Setup MATLAB 38 | uses: matlab-actions/setup-matlab@v2 39 | with: 40 | release: ${{ matrix.MATLABVersion }} 41 | products: > 42 | Symbolic_Math_Toolbox 43 | # Simulink Statistics_and_Machine_Learning_Toolbox 44 | # List required products above in the format shown (and uncomment them) 45 | # List of product strings: 46 | # Simulink 47 | # Statistics_and_Machine_Learning_Toolbox 48 | # Simulink_Coder 49 | # Econometrics_Toolbox 50 | # Deep_Learning_Toolbox 51 | 52 | 53 | # Run all the tests 54 | - name: Run SmokeTests 55 | uses: matlab-actions/run-command@v2 56 | with: 57 | command: openProject(pwd); RunAllTests; 58 | 59 | # Upload the test results as artifact 60 | - name: Upload TestResults 61 | if: ${{ always() }} 62 | uses: actions/upload-artifact@v4 63 | with: 64 | name: TestResults_${{ matrix.MATLABVersion }} 65 | path: ./public/* 66 | overwrite: true 67 | 68 | badge: 69 | if: ${{ always() }} 70 | needs: [test] 71 | strategy: 72 | fail-fast: false 73 | runs-on: ubuntu-latest 74 | steps: 75 | 76 | # Checks-out your repository 77 | - uses: actions/checkout@v4 78 | 79 | # Sets up R2023b 80 | - name: Setup MATLAB 81 | uses: matlab-actions/setup-matlab@v2 82 | with: 83 | release: R2024b 84 | 85 | # Download the test results from artifact 86 | - name: Download All TestResults 87 | uses: actions/download-artifact@v4 88 | with: 89 | path: public 90 | pattern: TestResults_* 91 | merge-multiple: true 92 | 93 | # Create the test results badge 94 | - name: Run PostSmokeTest 95 | uses: matlab-actions/run-command@v2 96 | with: 97 | command: openProject(pwd); PostSmokeTest; 98 | 99 | # Deploy reports to GitHub pages 100 | - name: Setup Pages 101 | uses: actions/configure-pages@v5 102 | - name: Upload pages artifact 103 | uses: actions/upload-pages-artifact@v3 104 | with: 105 | path: public 106 | - name: Deploy to GitHub Pages 107 | id: deployment 108 | uses: actions/deploy-pages@v4 109 | 110 | # Commit the JSON for the MATLAB releases badge 111 | - name: Commit changed files 112 | continue-on-error: true 113 | run: | 114 | git config user.name "${{ github.workflow }} by ${{ github.actor }}" 115 | git config user.email "<>" 116 | git pull 117 | git add Images/TestedWith.json 118 | git commit Images/TestedWith.json -m "Update CI badges ${{ github.ref_name }}" 119 | git fetch 120 | git push 121 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # List of untracked files to ignore 2 | 3 | # Autosave files 4 | *.asv 5 | *.m~ 6 | *.autosave 7 | *.slx.r* 8 | *.mdl.r* 9 | __pycache__ 10 | *.pyc 11 | */*.pyc 12 | 13 | # MATLAB Drive 14 | *.MATLABDriveTag 15 | 16 | # Compiled files 17 | *.mex* 18 | *.p 19 | 20 | # Compressed files 21 | *.zip 22 | 23 | # Packaged app and toolbox files 24 | *.mlappinstall 25 | *.mltbx 26 | 27 | # Deployable archives 28 | *.ctf 29 | 30 | # Generated helpsearch folders 31 | helpsearch*/ 32 | 33 | # Defined Simulink cache folder 34 | Utilities/SimulinkCache/* 35 | 36 | # Standard code generation folders 37 | slprj/ 38 | sccprj/ 39 | codegen/ 40 | 41 | # Code generation file 42 | *.eep 43 | *.elf 44 | *.hex 45 | *.bin 46 | 47 | # Cache files 48 | *.slxc 49 | 50 | # Project settings 51 | Utilities/ProjectSettings.mat 52 | 53 | # GitLab page folder 54 | public/ 55 | 56 | # Prevent accidentally committing your API key 57 | myAPIkey.txt 58 | 59 | # Live Task Repository 60 | MATLAB-Live-Task-for-Python 61 | 62 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | # Set up two testing paths 3 | - setup 4 | - test 5 | - deploy 6 | - release 7 | 8 | setup-job: 9 | tags: 10 | - matlab 11 | stage: setup 12 | script: 13 | - cd .. 14 | - if (test-path utilities) { rm -r -force utilities } 15 | - git clone git@insidelabs-git.mathworks.com:modular-curriculum-content/utilities.git 16 | - cd $CI_PROJECT_NAME 17 | allow_failure: false 18 | 19 | 20 | smoke-test: 21 | # Smoke tests should run all the time 22 | tags: 23 | # Add additional tags like (e.g. - arduino) as required 24 | # Make sure that the runner you plan to use matches the tags 25 | - matlab 26 | stage: test 27 | script: 28 | - matlab -batch "openProject(pwd);RunAllTests(true)" 29 | when: always 30 | allow_failure: true 31 | artifacts: 32 | paths: 33 | - public/* 34 | expire_in: 1 years 35 | 36 | pages: 37 | tags: 38 | - matlab 39 | stage: deploy 40 | script: 41 | - echo 'Deploying pages' 42 | artifacts: 43 | paths: 44 | - public 45 | 46 | smoke-test-solution: 47 | tags: 48 | - matlab 49 | stage: release 50 | script: 51 | - matlab -batch "proj = openProject(pwd); 52 | addpath(genpath(proj.RootFolder)); 53 | results = runtests(fullfile('InternalFiles','Tests','CI','SolnSmokeTests.m')); 54 | disp(table(results)); assertSuccess(results);" 55 | rules: 56 | # This test should always run when merging to main 57 | # And be available for manual running on any push 58 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH 59 | when: always 60 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH 61 | when: manual 62 | allow_failure: true 63 | 64 | file-test: 65 | tags: 66 | - matlab 67 | stage: release 68 | script: 69 | - matlab -batch "proj = openProject(pwd); 70 | addpath(proj.RootFolder+'/InternalFiles/Tests/CI'); 71 | results = runtests('OpenCloseFileTest.m'); 72 | disp(table(results)); assertSuccess(results);" 73 | rules: 74 | # This test should always run when merging to main 75 | # And be available for manual running on any push 76 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH 77 | when: always 78 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH 79 | when: manual 80 | allow_failure: true 81 | 82 | release-testing: 83 | tags: 84 | - matlab 85 | stage: release 86 | script: 87 | - matlab -batch "proj = openProject(pwd); 88 | cd ..; 89 | addpath(genpath(fullfile('utilities','TestingResources'))); 90 | runCMTests" 91 | rules: 92 | # This test should always run when merging to main 93 | # And be available for manual running on any push 94 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH 95 | when: always 96 | - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH 97 | when: manual 98 | allow_failure: true 99 | -------------------------------------------------------------------------------- /.vs/ProjectSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CurrentProjectSetting": null 3 | } -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/.vs/slnx.sqlite -------------------------------------------------------------------------------- /Apps/CurrentWeatherAppDemo.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Apps/CurrentWeatherAppDemo.mlapp -------------------------------------------------------------------------------- /Apps/CurrentWeatherAppStart.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Apps/CurrentWeatherAppStart.mlapp -------------------------------------------------------------------------------- /Apps/WeatherDisplay.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Apps/WeatherDisplay.mlapp -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | >_If you believe you have discovered a security vulnerability, please **do not** open an issue or make a pull request. Follow the instructions in the [SECURITY.md](SECURITY.md) file in this repository._ 4 | 5 | Thank you for your interest in contributing to a MathWorks repository! We encourage contributions large and small to this repository. 6 | 7 | **Contributions do not have to be code!** If you see a way to explain things more clearly or a great example of how to use something, please contribute it (or a link to your content). We welcome issues even if you don't code the solution. We also welcome pull requests to resolve issues that we haven't gotten to yet! 8 | 9 | ## How to give feedback 10 | * **Send us an email:** Contact the [MathWorks teaching resources team.](mailto:onlineteaching@mathworks.com) 11 | * **Open an issue:** Start by [creating an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue) in the repository that you're interested in. That will start a conversation with the maintainer. When you are creating a bug report, please include as many details as possible. Please remember that other people do not have your background or understanding of the issue; make sure you are clear and complete in your description. 12 | 13 | ## How to contribute to the repository 14 | * **Work in your own public fork:** If you choose to make a contribution, you should [fork the repository](https://docs.github.com/en/get-started/quickstart/fork-a-repo). This creates an editable copy on GitHub where you can write, test, and refine your changes. We suggest that you keep your changes small and focused on the issue you submitted. 15 | * **Sign a Contributor License Agreement (CLA):** We require that all outside contributors sign a [CLA](https://en.wikipedia.org/wiki/Contributor_License_Agreement) before we can accept your contribution. When you create a pull request (see below), we'll reach out to you if you do not already have one on file. Essentially, the CLA gives us permission to publish your contribution as part of the repository. 16 | * **Make a pull request:** "[Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)" is a confusing term, but it means exactly what it says: You're requesting that the maintainers of the repository pull your changes in. If you don't have a CLA on file, we'll reach out to you. Your contribution will be reviewed, and we may ask you to revise your pull request based on our feedback. Once everyone is satisfied, we'll merge your pull request into the repository. 17 | 18 | ## Guidelines 19 | 20 | We don't have best practices for writing MATLAB® code, but we do have some recommendations: 21 | 22 | * You should not have any warnings or errors in the [code analyzer report](http://www.mathworks.com/help/matlab/matlab_prog/matlab-code-analyzer-report.html) 23 | * [Loren Shure's blog](https://blogs.mathworks.com/loren) has [great advice on improving your MATLAB code](https://blogs.mathworks.com/loren/category/best-practice/) 24 | * Examples should be written as [live scripts](https://www.mathworks.com/help/matlab/matlab_prog/what-is-a-live-script-or-function.html) or [Simulink® models](https://www.mathworks.com/help/simulink/index.html). 25 | * We adhere to the [CommonMark](https://commonmark.org/) specification where it does not conflict with GitHub rendering. If you edit your Markdown in Visual Studio Code or a similar editor, it uses [markdownlint](https://github.com/DavidAnson/markdownlint) to highlight issues in your Markdown. 26 | 27 | **Again, thanks for contributing, and we look forward to your issues and pull requests!** 28 | -------------------------------------------------------------------------------- /FunctionLibrary/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/FunctionLibrary/.gitkeep -------------------------------------------------------------------------------- /FunctionLibrary/CheckPythonVersion.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/FunctionLibrary/CheckPythonVersion.mlx -------------------------------------------------------------------------------- /FunctionLibrary/helloworld.py: -------------------------------------------------------------------------------- 1 | print("Hello, "+name+"!") -------------------------------------------------------------------------------- /Images/AddCallbackFromContextMenu.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/AddCallbackFromContextMenu.mlx -------------------------------------------------------------------------------- /Images/AddCallbackInComponentBrowser.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/AddCallbackInComponentBrowser.mlx -------------------------------------------------------------------------------- /Images/AddFunction.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/AddFunction.mlx -------------------------------------------------------------------------------- /Images/AddMultipleComponentsToApp.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/AddMultipleComponentsToApp.mlx -------------------------------------------------------------------------------- /Images/AddOnsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/AddOnsIcon.png -------------------------------------------------------------------------------- /Images/AddProperty.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/AddProperty.mlx -------------------------------------------------------------------------------- /Images/EndIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/EndIcon.png -------------------------------------------------------------------------------- /Images/MouseThoughtBubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/MouseThoughtBubble.png -------------------------------------------------------------------------------- /Images/NatickTempPress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/NatickTempPress.png -------------------------------------------------------------------------------- /Images/NatickWind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/NatickWind.png -------------------------------------------------------------------------------- /Images/OpenInFX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/OpenInFX.png -------------------------------------------------------------------------------- /Images/OpenInMO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/OpenInMO.png -------------------------------------------------------------------------------- /Images/RGBTurkeys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/RGBTurkeys.png -------------------------------------------------------------------------------- /Images/RunPythonLiveTask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/RunPythonLiveTask.png -------------------------------------------------------------------------------- /Images/SeaSurfaceTemps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/SeaSurfaceTemps.png -------------------------------------------------------------------------------- /Images/TestedWith.json: -------------------------------------------------------------------------------- 1 | {"schemaVersion":1,"label":"Test Status","color":"success","message":"R2024a | R2024b"} 2 | -------------------------------------------------------------------------------- /Images/WeatherDashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/WeatherDashboard.png -------------------------------------------------------------------------------- /Images/WeatherStruct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/WeatherStruct.png -------------------------------------------------------------------------------- /Images/windTokyo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Images/windTokyo.gif -------------------------------------------------------------------------------- /InstructorResources/Solutions/CheckingTheWeatherSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/InstructorResources/Solutions/CheckingTheWeatherSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/CreateCurrentWeatherAppSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/InstructorResources/Solutions/CreateCurrentWeatherAppSoln.mlx -------------------------------------------------------------------------------- /InstructorResources/Solutions/UsingMATLABwithPythonSoln.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/InstructorResources/Solutions/UsingMATLABwithPythonSoln.mlx -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024, The MathWorks, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution 13 | * Neither the name of the The MathWorks, Inc. nor the names 14 | of its contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /MATLABwithPython.prj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /MainMenu.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/MainMenu.mlx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Programming: A Starter Project Using MATLAB with Python 3 | 4 | 5 | [![View on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://www.mathworks.com/matlabcentral/fileexchange/116490-programming-a-starter-project-using-matlab-and-python) or [![Open in MATLAB Online](https://www.mathworks.com/images/responsive/global/open-in-matlab-online.svg)](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=README.mlx) 6 | 7 | [![MATLAB Versions Tested](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FMathWorks-Teaching-Resources%2FProgramming-A-Starter-Project-Using-MATLAB-and-Python%2Frelease%2FImages%2FTestedWith.json)](https://MathWorks-Teaching-Resources.github.io/Programming-A-Starter-Project-Using-MATLAB-and-Python) 8 | 9 | **Curriculum Module** 10 | 11 | _Created with R2024a. Compatible with R2024a and later releases._ 12 | 13 | # Information 14 | 15 | This curriculum module contains interactive [MATLAB® live scripts](https://www.mathworks.com/products/matlab/live-editor.html) that teach fundamental concepts and basic terminology related to programming computers. 16 | 17 | # Prerequisite Domain Knowledge 18 | 19 | This module assumes familiarity with basic programming concepts such as variables, data types, and functions, structures including arrays and structs, and control flows including if/else as well as how to use them in MATLAB. These ideas are all presented with interactive examples in [Fundamentals of Programming](https://www.mathworks.com/matlabcentral/fileexchange/103225-fundamentals-of-programming), [Programming: Organizing Data](https://www.mathworks.com/matlabcentral/fileexchange/115900-programming-organizing-data), [Programming: Structuring Code](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code). 20 | 21 | 22 | ## Background 23 | 24 | You can use these live scripts as demonstrations in lectures, class activities, or interactive assignments outside class. This module explores interactions between systems by using the OpenWeather API and calling into Python from MATLAB. **Programming: A Starter Project Using MATLAB with Python** covers using the Run Python Code Live Task to run provided Python code, accessing the OpenWeather API to check the weather, extracting useful data from the API call, and using App Designer to create an app with a personalized weather display. 25 | 26 | 27 | The instructions inside the live scripts will guide you through the exercises and activities. Get started with each live script by running it one section at a time. To stop running the script or a section midway (for example, when an animation is in progress), use the EndIcon.png Stop button in the **RUN** section of the **Live Editor** tab in the MATLAB Toolstrip. 28 | 29 | ## Contact Us 30 | 31 | Solutions are available upon instructor request. Contact the [MathWorks teaching resources team](mailto:onlineteaching@mathworks.com) if you would like to request solutions, provide feedback, or if you have a question. 32 | 33 | 34 | ## Prerequisites 35 | 36 | This module assumes familiarity with basic programming concepts such as variables, data types, and functions, structures including arrays and structs, and control flows including if/else as well as how to use them in MATLAB. These ideas are all presented with interactive examples in [Fundamentals of Programming](https://github.com/MathWorks-Teaching-Resources/Fundamentals-of-Programming), [Programming: Organizing Data](https://github.com/MathWorks-Teaching-Resources/Programming-Organizing-Data), [Programming: Structuring Code](https://github.com/MathWorks-Teaching-Resources/Programming-Structuring-Code). 37 | 38 | 39 | ## Getting Started 40 | ### Accessing the Module 41 | ### **On MATLAB Online:** 42 | 43 | Use the [OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj) link to download the module. You will be prompted to log in or create a MathWorks account. The project will be loaded, and you will see an app with several navigation options to get you started. 44 | 45 | ### **On Desktop:** 46 | 47 | Download or clone this repository. Open MATLAB, navigate to the folder containing these scripts and double\-click on [MATLABwithPython.prj](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=README.mlx). It will add the appropriate files to your MATLAB path and open an app that asks you where you would like to start. 48 | 49 | 50 | Ensure you have all the required products (listed below) installed. If you need to include a product, add it using the Add\-On Explorer. To install an add\-on, go to the **Home** tab and select AddOnsIcon.png **Add-Ons** > **Get Add-Ons**. 51 | 52 | 53 | ## Products 54 | 55 | MATLAB® is used throughout. Tools from the Symbolic Math Toolbox™ are used to convert between different unit systems in the weather applications. 56 | 57 | # Scripts 58 | ## [**UsingMATLABwithPython.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=Scripts/UsingMATLABwithPython.mlx) 59 | | | | 60 | | :-- | :-- | 61 | | **Introductory script**
| **In this script, students will...**
| 62 | | RunPythonLiveTask.png
| $\bullet$ check that an appropriate version of Python is installed and visible within MATLAB
$\bullet$ explore the Run Python Code Live Task
$\bullet$ try running Python commands and a Python script from MATLAB
| 63 | | | | 64 | 65 | ## [**CheckingTheWeather.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=Scripts/CheckingTheWeather.mlx) 66 | | | | 67 | | :-- | :-- | 68 | | **Investigatory script**
| **In this script, students will...**
| 69 | | WeatherStruct.png
| $\bullet$ set up an account with OpenWeather to create your own API key
$\bullet$ use existing Python code to make an API call to OpenWeather
$\bullet$ use MATLAB to explore the data returned by the API call, including data type conversions and unit conversions
| 70 | | | | 71 | 72 | ## [**CreateCurrentWeatherApp.mlx**](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=Scripts/CreateCurrentWeatherApp.mlx) 73 | | | | 74 | | :-- | :-- | 75 | | **Application script**
| **In this script, students will...**
| 76 | | WeatherDashboard.png
| $\bullet$ use App Designer to build a custom app using the code from CheckingTheWeather.mlx
$\bullet$ create callbacks, properties, and functions
$\bullet$ design and organize a UI with drag and drop elements
$\bullet$ reuse code from CheckingTheWeather in a new context
| 77 | | | | 78 | 79 | # Apps 80 | 81 | Both of these apps require running Python from MATLAB, as set up in UsingMATLABwithPython and an OpenWeather API key, as set up in CheckingTheWeather. 82 | 83 | - **CurrentWeatherAppDemo.mlapp** shows the results of working through CreateCurrentWeatherApp. 84 | - **WeatherDisplay.mlapp** shows one elaborated version of the basic current weather app. 85 | 86 | # License 87 | 88 | The license for this module is available in the [LICENSE.md](https://github.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/blob/release/LICENSE.md). 89 | 90 | # Related Courseware Modules 91 | | | | | 92 | | :-- | :-- | :-- | 93 | | **Courseware Module**
| **Sample Content**
| **Available on:**
| 94 | | [**Fundamentals of Programming**](https://www.mathworks.com/matlabcentral/fileexchange/103225-fundamentals-of-programming)
Learn the basics of how to make a computer
accept, store, and compute with information
| MouseThoughtBubble.png
| [OpenInFX.png](https://www.mathworks.com/matlabcentral/fileexchange/103225-fundamentals-of-programming)
[OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Fundamentals-of-Programming&project=FundamentalsofProgramming.prj)
[GitHub](https://github.com/MathWorks-Teaching-Resources/Fundamentals-of-Programming)
| 95 | | [**Programming: Structuring Code**](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code)
Learn how to organize your code into functions,
debug, comment, and share
| RGBTurkeys.png
| [OpenInFX.png](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code)
[OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-Structuring-Code&project=StructuringCode.prj)
[GitHub](https://github.com/MathWorks-Teaching-Resources/Programming-Structuring-Code)
| 96 | | [**Programming: Organizing Data**](https://www.mathworks.com/matlabcentral/fileexchange/115900-programming-organizing-data)
Learn more about strings, numeric data types,
memory, and ways of storing data
| SeaSurfaceTemps.png
| [OpenInFX.png](https://www.mathworks.com/matlabcentral/fileexchange/115900-programming-organizing-data)
[OpenInMO.png](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-Organizing-Data&project=OrganizingData.prj)
[GitHub](https://github.com/MathWorks-Teaching-Resources/Programming-Organizing-Data)
| 97 | | | | | 98 | 99 | 100 | Or feel free to explore our other [modular courseware content](https://www.mathworks.com/matlabcentral/fileexchange/?q=tag%3A%22courseware+module%22&sort=downloads_desc_30d). 101 | 102 | # Educator Resources 103 | - [Educator Page](https://www.mathworks.com/academia/educators.html) 104 | 105 | # Contribute 106 | 107 | Looking for more? Find an issue? Have a suggestion? Please contact the [MathWorks teaching resources team](mailto:%20onlineteaching@mathworks.com). If you want to contribute directly to this project, you can find information about how to do so in the [CONTRIBUTING.md](https://github.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/blob/release/CONTRIBUTING.md) page on GitHub. 108 | 109 | # Acknowledgments 110 | 111 | Many thanks to Blake Naccarato on his suggestions for improvement. 112 | 113 | 114 | *©* Copyright 2024 The MathWorks™, Inc 115 | 116 | 117 | -------------------------------------------------------------------------------- /README.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/README.mlx -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Vulnerabilities 2 | 3 | If you believe you have discovered a security vulnerability, please report it to 4 | [security@mathworks.com](mailto:security@mathworks.com). Please see 5 | [MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html) 6 | for additional information. -------------------------------------------------------------------------------- /Scripts/CheckingTheWeather.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Scripts/CheckingTheWeather.mlx -------------------------------------------------------------------------------- /Scripts/CreateCurrentWeatherApp.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Scripts/CreateCurrentWeatherApp.mlx -------------------------------------------------------------------------------- /Scripts/UsingMATLABwithPython.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Scripts/UsingMATLABwithPython.mlx -------------------------------------------------------------------------------- /Scripts/checkcurrentweather.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | Python 3.8 code 4 | Created on Thu Jan 4 20:41:45 2018 5 | Modified May 2022 6 | 7 | @author: Heather Gorr 8 | Updated by: Emma Smith Zbarsky 9 | Copyright 2018-2022 The MathWorks, Inc. 10 | 11 | Create the Openweather API-structured URL using One Call 12 | as described in the documentation 13 | https://openweathermap.org/api/one-call-api 14 | This API is licensed under CC BY-SA 4.0, as documented here: 15 | https://creativecommons.org/licenses/by-sa/4.0/ 16 | ''' 17 | 18 | # checkcurrentweather.py 19 | import datetime 20 | import json 21 | import urllib.request 22 | 23 | BASE_URL = 'http://api.openweathermap.org/data/2.5/weather?lat={}&lon={}&units={}&appid={}' 24 | 25 | def get_weather(lat,lon,apikey,**kwargs): 26 | '''get current conditions in specified location, e.g., 27 | lat = 42.2775 N, lon = 71.3468 W is Natick, MA, US 28 | get_current_weather('42.2775','-71.3468',key,units='metric')''' 29 | 30 | # Initialize json_data 31 | json_data = {'Feedback': 'nothing'} 32 | 33 | # Set a default of imperial units 34 | info = {'units':'imperial'} 35 | for key, value in kwargs.items(): 36 | info[key] = value 37 | 38 | try: 39 | url = BASE_URL.format(lat,lon,info['units'],apikey) 40 | json_data = json.loads(urllib.request.urlopen(url).read()) 41 | except urllib.error.URLError: 42 | # if the One Call weather API doesn't work, return an error 43 | print('We cannot access the weather service') 44 | 45 | return json_data 46 | 47 | 48 | def parse_current_json(json_data): 49 | '''parse and extract json data from the current weather data''' 50 | 51 | # Initialize weather_info 52 | weather_info = {'Feedback': 'nothing'} 53 | 54 | try: 55 | # select data of interest from dictionary 56 | weather_info = json_data['main'] 57 | # add current date and time 58 | weather_info['local_time'] = str(datetime.datetime.now()) 59 | weather_info['current_time'] = json_data['dt'] 60 | # make sure values are returned as floats 61 | weather_info['temp'] = float(weather_info['temp']) 62 | weather_info['feels_like'] = float(weather_info['feels_like']) 63 | weather_info['pressure'] = float(weather_info['pressure']) 64 | weather_info['humidity'] = float(weather_info['humidity']) 65 | weather_info['wind_speed'] = float(json_data['wind']['speed']) 66 | weather_info['wind_deg'] = float(json_data['wind']['deg']) 67 | weather_info['clouds'] = float(json_data['clouds']['all']) 68 | # Seconds shifted from UTC for location 69 | weather_info['timezone'] = json_data['timezone'] 70 | # UTC Unix time 71 | weather_info['sunrise'] = json_data['sys']['sunrise'] 72 | weather_info['sunset'] = json_data['sys']['sunset'] 73 | # String 74 | weather_info['city_name'] = json_data['name'] 75 | # Weather description as list 76 | weather_info['weather'] = json_data['weather'] 77 | 78 | except KeyError as e: 79 | print('Something went wrong while parsing current json') 80 | raise e 81 | 82 | return weather_info -------------------------------------------------------------------------------- /SoftwareTests/CheckTestResults.m: -------------------------------------------------------------------------------- 1 | classdef CheckTestResults < matlab.unittest.TestCase 2 | 3 | properties (SetAccess = protected) 4 | end 5 | 6 | properties (ClassSetupParameter) 7 | Project = {currentProject()}; 8 | end 9 | 10 | properties (TestParameter) 11 | Version 12 | end 13 | 14 | 15 | methods (TestParameterDefinition,Static) 16 | 17 | function Version = GetResults(Project) 18 | RootFolder = Project.RootFolder; 19 | Version = dir(fullfile(RootFolder,"public","TestResults*.txt")); 20 | Version = extractBetween([Version.name],"TestResults_",".txt"); 21 | end 22 | 23 | end 24 | 25 | methods (TestClassSetup) 26 | 27 | function SetUpSmokeTest(testCase,Project) 28 | try 29 | currentProject; 30 | catch 31 | error("Project is not loaded.") 32 | end 33 | end 34 | 35 | end 36 | 37 | methods(Test) 38 | 39 | function CheckResults(testCase,Version) 40 | File = fullfile("public","TestResults_"+Version+".txt"); 41 | Results = readtable(File,TextType="string"); 42 | if ~all(Results.Passed) 43 | error("Some of the tests did not pass.") 44 | end 45 | end 46 | 47 | end 48 | 49 | end -------------------------------------------------------------------------------- /SoftwareTests/CreateBadge.m: -------------------------------------------------------------------------------- 1 | % Create the test suite with SmokeTest and Function test if they exist 2 | Suite = testsuite("CheckTestResults"); 3 | 4 | % Create a runner with no plugins 5 | Runner = matlab.unittest.TestRunner.withNoPlugins; 6 | 7 | % Run the test suite 8 | Results = Runner.run(Suite); 9 | 10 | % Format the results in a table and save them 11 | Results = table(Results'); 12 | Results = Results(Results.Passed,:); 13 | Version = extractBetween(string(Results.Name),"Version=",")"); 14 | 15 | 16 | % Format the JSON file 17 | Badge = struct; 18 | Badge.schemaVersion = 1; 19 | Badge.label = "Tested with"; 20 | if size(Results,1) >= 1 21 | Badge.color = "success" 22 | Badge.message = join(Version," | "); 23 | else 24 | Badge.color = "failure"; 25 | Badge.message = "Pipeline fails"; 26 | end 27 | Badge = jsonencode(Badge); 28 | writelines(Badge,fullfile("Images","TestedWith.json")); -------------------------------------------------------------------------------- /SoftwareTests/FunctionTests.m: -------------------------------------------------------------------------------- 1 | classdef FunctionTests < matlab.unittest.TestCase 2 | 3 | % https://www.mathworks.com/help/matlab/matlab_prog/use-parameters-in-class-based-tests.html 4 | 5 | methods(Test) 6 | 7 | end % methods 8 | 9 | end % classdef -------------------------------------------------------------------------------- /SoftwareTests/OrigSmokeTests.m: -------------------------------------------------------------------------------- 1 | classdef SmokeTests < matlab.unittest.TestCase 2 | 3 | properties (ClassSetupParameter) 4 | Project = {''}; 5 | end 6 | 7 | properties (TestParameter) 8 | Scripts; 9 | end 10 | 11 | methods (TestParameterDefinition,Static) 12 | 13 | function Scripts = GetScriptName(Project) 14 | RootFolder = currentProject().RootFolder; 15 | Scripts = dir(fullfile(RootFolder,"Scripts","*.mlx")); 16 | Scripts = {Scripts.name}; 17 | end 18 | 19 | end 20 | 21 | methods (TestClassSetup) 22 | 23 | function SetUpSmokeTest(testCase,Project) 24 | try 25 | currentProject; 26 | catch ME 27 | warning("Project is not loaded.") 28 | end 29 | end 30 | 31 | 32 | end 33 | 34 | 35 | 36 | methods(Test) 37 | 38 | function SmokeRun(testCase,Scripts) 39 | Filename = string(Scripts); 40 | switch (Filename) 41 | case "CreateCurrentWeatherApp.mlx" 42 | disp("Skipping " + Filename) 43 | case "CheckingTheWeather.mlx" 44 | txt = readlines("Response.json"); 45 | pycode = ["import checkcurrentweather" 46 | "import json" 47 | "" 48 | "json_data = json.loads(txt)" 49 | "currentWeather = checkcurrentweather.parse_current_json(json_data)" 50 | ]; 51 | APISmokeTest(testCase,Filename,pycode,txt) 52 | case "WeatherForecast.mlx" 53 | % txt = readlines("ResponseOneCall.json"); 54 | % pycode = ["import checkweather" 55 | % "" 56 | % "json_data = json.loads(txt)" 57 | % "currentWeather = checkweather.parse_current_json(json_data)" 58 | % "forecastWeather = checkweather.parse_forecast_json(json_data)" 59 | % ]; 60 | % APISmokeTest(testCase,Filename,pycode,txt) 61 | case "SampleWeatherDashboard.mlx" 62 | 63 | otherwise 64 | SimpleSmokeTest(testCase,Filename) 65 | end 66 | end 67 | 68 | end 69 | 70 | 71 | methods (Access = private) 72 | 73 | function APISmokeTest(testCase,Filename,pycode,txt) 74 | RootFolder = currentProject().RootFolder; 75 | cd(RootFolder) 76 | cd Scripts 77 | if Filename == "CheckingTheWeather.mlx" 78 | [currentWeather] = pyrun(pycode, "currentWeather","txt",txt); 79 | elseif Filename == "WeatherForecast.mlx" 80 | [currentWeather,forecastWeather] = pyrun(pycode,["currentWeather","forecastWeather"],"txt",txt); 81 | end 82 | 83 | disp(">> Running " + Filename); 84 | try 85 | run(fullfile(Filename)); 86 | catch ME 87 | testCase.verifyTrue(false,ME.message); 88 | end 89 | 90 | try 91 | % Log the opened figures to the test reports 92 | Figures = findall(groot,'Type','figure'); 93 | Figures = flipud(Figures); 94 | if ~isempty(Figures) 95 | for f = 1:size(Figures,1) 96 | FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f)); 97 | log(testCase,1,FigDiag); 98 | end 99 | end 100 | catch ME 101 | disp("Failed to capture images") 102 | end 103 | close all 104 | end 105 | 106 | function RunMyFile(~,Filename) 107 | run(Filename); 108 | end 109 | 110 | function SimpleSmokeTest(testCase,Filename) 111 | 112 | % Run the Smoke test 113 | RootFolder = currentProject().RootFolder; 114 | cd(RootFolder) 115 | disp(">> Running " + Filename); 116 | try 117 | RunMyFile(testCase,Filename) 118 | catch ME 119 | testCase.verifyTrue(false,ME.message); 120 | end 121 | 122 | % Log the opened figures to the test reports 123 | try 124 | Figures = findall(groot,'Type','figure'); 125 | Figures = flipud(Figures); 126 | if ~isempty(Figures) 127 | for f = 1:size(Figures,1) 128 | FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f)); 129 | log(testCase,1,FigDiag); 130 | end 131 | end 132 | catch ME 133 | disp("Failed to capture figures") 134 | end 135 | close all 136 | 137 | end 138 | 139 | end 140 | 141 | methods (TestClassTeardown) 142 | 143 | function closeAllFigure(testCase) 144 | close all force % Close figure windows 145 | end 146 | 147 | end % methods (TestClassTeardown) 148 | 149 | end -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostCheckingTheWeather.m: -------------------------------------------------------------------------------- 1 | % Post-run script for CheckingTheWeather.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostCheckingTheWeatherSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for CheckingTheWeatherSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | writelines("",fullfile(currentProject().RootFolder,"Scripts","myAPIkey.txt")) 5 | if exist(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","Response.json"),"file") 6 | delete(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","Response.json")) 7 | end -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostCreateCurrentWeatherApp.m: -------------------------------------------------------------------------------- 1 | % Post-run script for CreateCurrentWeatherApp.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostCreateCurrentWeatherAppSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for CreateCurrentWeatherAppSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | delete(findall(groot,'Name','MATLAB App')) -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostUsingMATLABwithPython.m: -------------------------------------------------------------------------------- 1 | % Post-run script for UsingMATLABwithPython.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostFiles/PostUsingMATLABwithPythonSoln.m: -------------------------------------------------------------------------------- 1 | % Post-run script for UsingMATLABwithPythonSoln.mlx 2 | % ---- Post-run commands ----- 3 | 4 | -------------------------------------------------------------------------------- /SoftwareTests/PostSmokeTest.m: -------------------------------------------------------------------------------- 1 | function PostSmokeTest(ShowReport) 2 | arguments 3 | ShowReport (1,1) logical = false; 4 | end 5 | 6 | import matlab.unittest.plugins.TestRunnerPlugin; 7 | 8 | % Create the runner: 9 | Runner = matlab.unittest.TestRunner.withTextOutput; 10 | 11 | % Create report folder: 12 | Folder = fullfile(currentProject().RootFolder,"public"); 13 | if ~isfolder(Folder) 14 | mkdir(Folder) 15 | end 16 | 17 | % Add HTML plugin: 18 | Plugin = matlab.unittest.plugins.TestReportPlugin.producingHTML(Folder,... 19 | "IncludingPassingDiagnostics",true,... 20 | "IncludingCommandWindowText",false,... 21 | "LoggingLevel",matlab.automation.Verbosity(1)); 22 | Runner.addPlugin(Plugin); 23 | 24 | 25 | % Create Test Suite 26 | Suite = testsuite("CheckTestResults"); 27 | 28 | % Run the test suite 29 | Results = Runner.run(Suite); 30 | 31 | 32 | % Format the results in a table and save them 33 | Results = table(Results'); 34 | Version = extractBetween(string(Results.Name),"Version=",")"); 35 | Passed = Results.Passed; 36 | 37 | % Add link to other report 38 | File = fileread(fullfile("public","index.html")); 39 | for iVer = 1:length(Version) 40 | File = replace(File,"Version="+Version(iVer),... 41 | sprintf('%s',Version(iVer),"Version="+Version(iVer))); 42 | end 43 | writelines(File,fullfile("public","index.html"),"WriteMode","overwrite"); 44 | 45 | % Format the JSON file 46 | Badge = struct; 47 | Badge.schemaVersion = 1; 48 | Badge.label = "Test Status"; 49 | if all(Passed) 50 | Badge.color = "success"; 51 | Badge.message = join("R"+Version," | "); 52 | elseif any(Passed) 53 | Badge.color = "yellowgreen"; 54 | Badge.message = join("R") 55 | elseif all(~Passed) 56 | Badge.color = "critical"; 57 | Badge.message = join("R"+Version," | "); 58 | end 59 | Badge = jsonencode(Badge); 60 | writelines(Badge,fullfile("Images","TestedWith.json")); 61 | 62 | if ShowReport 63 | web(fullfile(Folder,"index.html")) 64 | end 65 | 66 | end -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreCheckingTheWeather.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for CheckingTheWeather.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | txt = readlines("Response.json"); 7 | curpath = pwd; 8 | mypath = fullfile(currentProject().RootFolder,"Scripts"); 9 | cd(mypath) 10 | pycode = ["import checkcurrentweather" 11 | "import json" 12 | "" 13 | "json_data = json.loads(txt)" 14 | "currentWeather = checkcurrentweather.parse_current_json(json_data)" 15 | ]; 16 | [currentWeather] = pyrun(pycode, "currentWeather","txt",txt); 17 | cd(curpath) -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreCheckingTheWeatherSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for CheckingTheWeatherSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | try 7 | copyfile(fullfile(currentProject().RootFolder,"InternalFiles","Solutions","myAPIkey.txt"),... 8 | fullfile(currentProject().RootFolder,"Scripts","myAPIkey.txt")) 9 | catch 10 | copyfile("Response.json",fullfile(currentProject().RootFolder,"InstructorResources","Solutions","Response.json")) 11 | pycode = ["import checkcurrentweather" 12 | "import json" 13 | "" 14 | "json_data = json.load(open(""Response.json""))" 15 | "currentWeather = checkcurrentweather.parse_current_json(json_data)" 16 | ]; 17 | apikey = "TestString"; 18 | pyrun = @(txt,out,varargin)TestPyRun(pycode,out,varargin); 19 | end 20 | 21 | function out = TestPyRun(txt,in,varargin) 22 | out = pyrun(txt,in); 23 | end 24 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreCreateCurrentWeatherApp.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for CreateCurrentWeatherApp.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | appdesigner = @()disp("Open App Designer here."); -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreCreateCurrentWeatherAppSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for CreateCurrentWeatherAppSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | open = @(x)run(x); 7 | 8 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreUsingMATLABwithPython.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for UsingMATLABwithPython.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/PreUsingMATLABwithPythonSoln.m: -------------------------------------------------------------------------------- 1 | % Pre-run script for UsingMATLABwithPythonSoln.mlx 2 | % ---- Known Issues ----- 3 | KnownIssuesID = ""; 4 | % ---- Pre-run commands ----- 5 | 6 | -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/Response.json: -------------------------------------------------------------------------------- 1 | {"coord":{"lon":-71.3468,"lat":42.2775},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"base":"stations","main":{"temp":274.86,"feels_like":270.03,"temp_min":273.44,"temp_max":276.25,"pressure":1003,"humidity":76},"visibility":10000,"wind":{"speed":5.66,"deg":280,"gust":10.8},"clouds":{"all":75},"dt":1710986897,"sys":{"type":2,"id":2005486,"country":"US","sunrise":1710931672,"sunset":1710975450},"timezone":-14400,"id":4944994,"name":"Natick","cod":200} -------------------------------------------------------------------------------- /SoftwareTests/PreFiles/ResponseOneCall.json: -------------------------------------------------------------------------------- 1 | { 2 | "lat":33.44, 3 | "lon":-94.04, 4 | "timezone":"America/Chicago", 5 | "timezone_offset":-18000, 6 | "current":{ 7 | "dt":1684929490, 8 | "sunrise":1684926645, 9 | "sunset":1684977332, 10 | "temp":292.55, 11 | "feels_like":292.87, 12 | "pressure":1014, 13 | "humidity":89, 14 | "dew_point":290.69, 15 | "uvi":0.16, 16 | "clouds":53, 17 | "visibility":10000, 18 | "wind_speed":3.13, 19 | "wind_deg":93, 20 | "wind_gust":6.71, 21 | "weather":[ 22 | { 23 | "id":803, 24 | "main":"Clouds", 25 | "description":"broken clouds", 26 | "icon":"04d" 27 | } 28 | ] 29 | }, 30 | "minutely":[ 31 | { 32 | "dt":1684929540, 33 | "precipitation":0 34 | } 35 | ], 36 | "hourly":[ 37 | { 38 | "dt":1684926000, 39 | "temp":292.01, 40 | "feels_like":292.33, 41 | "pressure":1014, 42 | "humidity":91, 43 | "dew_point":290.51, 44 | "uvi":0, 45 | "clouds":54, 46 | "visibility":10000, 47 | "wind_speed":2.58, 48 | "wind_deg":86, 49 | "wind_gust":5.88, 50 | "weather":[ 51 | { 52 | "id":803, 53 | "main":"Clouds", 54 | "description":"broken clouds", 55 | "icon":"04n" 56 | } 57 | ], 58 | "pop":0.15 59 | } 60 | ], 61 | "daily":[ 62 | { 63 | "dt":1684951200, 64 | "sunrise":1684926645, 65 | "sunset":1684977332, 66 | "moonrise":1684941060, 67 | "moonset":1684905480, 68 | "moon_phase":0.16, 69 | "summary":"Expect a day of partly cloudy with rain", 70 | "temp":{ 71 | "day":299.03, 72 | "min":290.69, 73 | "max":300.35, 74 | "night":291.45, 75 | "eve":297.51, 76 | "morn":292.55 77 | }, 78 | "feels_like":{ 79 | "day":299.21, 80 | "night":291.37, 81 | "eve":297.86, 82 | "morn":292.87 83 | }, 84 | "pressure":1016, 85 | "humidity":59, 86 | "dew_point":290.48, 87 | "wind_speed":3.98, 88 | "wind_deg":76, 89 | "wind_gust":8.92, 90 | "weather":[ 91 | { 92 | "id":500, 93 | "main":"Rain", 94 | "description":"light rain", 95 | "icon":"10d" 96 | } 97 | ], 98 | "clouds":92, 99 | "pop":0.47, 100 | "rain":0.15, 101 | "uvi":9.23 102 | } 103 | ], 104 | "alerts": [ 105 | { 106 | "sender_name": "NWS Philadelphia - Mount Holly (New Jersey, Delaware, Southeastern Pennsylvania)", 107 | "event": "Small Craft Advisory", 108 | "start": 1684952747, 109 | "end": 1684988747, 110 | "description": "...SMALL CRAFT ADVISORY REMAINS IN EFFECT FROM 5 PM THIS\nAFTERNOON TO 3 AM EST FRIDAY...\n* WHAT...North winds 15 to 20 kt with gusts up to 25 kt and seas\n3 to 5 ft expected.\n* WHERE...Coastal waters from Little Egg Inlet to Great Egg\nInlet NJ out 20 nm, Coastal waters from Great Egg Inlet to\nCape May NJ out 20 nm and Coastal waters from Manasquan Inlet\nto Little Egg Inlet NJ out 20 nm.\n* WHEN...From 5 PM this afternoon to 3 AM EST Friday.\n* IMPACTS...Conditions will be hazardous to small craft.", 111 | "tags": [] 112 | } 113 | ] 114 | } -------------------------------------------------------------------------------- /SoftwareTests/Response.json: -------------------------------------------------------------------------------- 1 | {"coord":{"lon":-71.3468,"lat":42.2775},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"base":"stations","main":{"temp":274.86,"feels_like":270.03,"temp_min":273.44,"temp_max":276.25,"pressure":1003,"humidity":76},"visibility":10000,"wind":{"speed":5.66,"deg":280,"gust":10.8},"clouds":{"all":75},"dt":1710986897,"sys":{"type":2,"id":2005486,"country":"US","sunrise":1710931672,"sunset":1710975450},"timezone":-14400,"id":4944994,"name":"Natick","cod":200} -------------------------------------------------------------------------------- /SoftwareTests/ResponseOneCall.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "lat":33.44, 4 | "lon":-94.04, 5 | "timezone":"America/Chicago", 6 | "timezone_offset":-18000, 7 | "current":{ 8 | "dt":1684929490, 9 | "sunrise":1684926645, 10 | "sunset":1684977332, 11 | "temp":292.55, 12 | "feels_like":292.87, 13 | "pressure":1014, 14 | "humidity":89, 15 | "dew_point":290.69, 16 | "uvi":0.16, 17 | "clouds":53, 18 | "visibility":10000, 19 | "wind_speed":3.13, 20 | "wind_deg":93, 21 | "wind_gust":6.71, 22 | "weather":[ 23 | { 24 | "id":803, 25 | "main":"Clouds", 26 | "description":"broken clouds", 27 | "icon":"04d" 28 | } 29 | ] 30 | }, 31 | "minutely":[ 32 | { 33 | "dt":1684929540, 34 | "precipitation":0 35 | } 36 | ], 37 | "hourly":[ 38 | { 39 | "dt":1684926000, 40 | "temp":292.01, 41 | "feels_like":292.33, 42 | "pressure":1014, 43 | "humidity":91, 44 | "dew_point":290.51, 45 | "uvi":0, 46 | "clouds":54, 47 | "visibility":10000, 48 | "wind_speed":2.58, 49 | "wind_deg":86, 50 | "wind_gust":5.88, 51 | "weather":[ 52 | { 53 | "id":803, 54 | "main":"Clouds", 55 | "description":"broken clouds", 56 | "icon":"04n" 57 | } 58 | ], 59 | "pop":0.15 60 | } 61 | ], 62 | "daily":[ 63 | { 64 | "dt":1684951200, 65 | "sunrise":1684926645, 66 | "sunset":1684977332, 67 | "moonrise":1684941060, 68 | "moonset":1684905480, 69 | "moon_phase":0.16, 70 | "summary":"Expect a day of partly cloudy with rain", 71 | "temp":{ 72 | "day":299.03, 73 | "min":290.69, 74 | "max":300.35, 75 | "night":291.45, 76 | "eve":297.51, 77 | "morn":292.55 78 | }, 79 | "feels_like":{ 80 | "day":299.21, 81 | "night":291.37, 82 | "eve":297.86, 83 | "morn":292.87 84 | }, 85 | "pressure":1016, 86 | "humidity":59, 87 | "dew_point":290.48, 88 | "wind_speed":3.98, 89 | "wind_deg":76, 90 | "wind_gust":8.92, 91 | "weather":[ 92 | { 93 | "id":500, 94 | "main":"Rain", 95 | "description":"light rain", 96 | "icon":"10d" 97 | } 98 | ], 99 | "clouds":92, 100 | "pop":0.47, 101 | "rain":0.15, 102 | "uvi":9.23 103 | } 104 | ], 105 | "alerts": [ 106 | { 107 | "sender_name": "NWS Philadelphia - Mount Holly (New Jersey, Delaware, Southeastern Pennsylvania)", 108 | "event": "Small Craft Advisory", 109 | "start": 1684952747, 110 | "end": 1684988747, 111 | "description": "...SMALL CRAFT ADVISORY REMAINS IN EFFECT FROM 5 PM THIS\nAFTERNOON TO 3 AM EST FRIDAY...\n* WHAT...North winds 15 to 20 kt with gusts up to 25 kt and seas\n3 to 5 ft expected.\n* WHERE...Coastal waters from Little Egg Inlet to Great Egg\nInlet NJ out 20 nm, Coastal waters from Great Egg Inlet to\nCape May NJ out 20 nm and Coastal waters from Manasquan Inlet\nto Little Egg Inlet NJ out 20 nm.\n* WHEN...From 5 PM this afternoon to 3 AM EST Friday.\n* IMPACTS...Conditions will be hazardous to small craft.", 112 | "tags": [ 113 | 114 | ] 115 | } 116 | ] 117 | } 118 | 119 | -------------------------------------------------------------------------------- /SoftwareTests/ResponseOneCallOneLine.json: -------------------------------------------------------------------------------- 1 | {"lat":33.44,"lon":-94.04,"timezone":"America/Chicago","timezone_offset":-18000,"current":{"dt":1684929490,"sunrise":1684926645,"sunset":1684977332,"temp":292.55,"feels_like":292.87,"pressure":1014,"humidity":89,"dew_point":290.69,"uvi":0.16,"clouds":53,"visibility":10000,"wind_speed":3.13,"wind_deg":93,"wind_gust":6.71,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}]},"minutely":[{"dt":1684929540,"precipitation":0}],"hourly":[{"dt":1684926000,"temp":292.01,"feels_like":292.33,"pressure":1014,"humidity":91,"dew_point":290.51,"uvi":0,"clouds":54,"visibility":10000,"wind_speed":2.58,"wind_deg":86,"wind_gust":5.88,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"pop":0.15}],"daily":[{"dt":1684951200,"sunrise":1684926645,"sunset":1684977332,"moonrise":1684941060,"moonset":1684905480,"moon_phase":0.16,"summary":"Expect a day of partly cloudy with rain","temp":{"day":299.03,"min":290.69,"max":300.35,"night":291.45,"eve":297.51,"morn":292.55},"feels_like":{"day":299.21,"night":291.37,"eve":297.86,"morn":292.87},"pressure":1016,"humidity":59,"dew_point":290.48,"wind_speed":3.98,"wind_deg":76,"wind_gust":8.92,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"clouds":92,"pop":0.47,"rain":0.15,"uvi":9.23} ],"alerts": [{"sender_name": "NWS Philadelphia - Mount Holly (New Jersey, Delaware, Southeastern Pennsylvania)","event": "Small Craft Advisory","start": 1684952747,"end": 1684988747,"description": "...SMALL CRAFT ADVISORY REMAINS IN EFFECT FROM 5 PM THIS\nAFTERNOON TO 3 AM EST FRIDAY...\n* WHAT...North winds 15 to 20 kt with gusts up to 25 kt and seas\n3 to 5 ft expected.\n* WHERE...Coastal waters from Little Egg Inlet to Great Egg\nInlet NJ out 20 nm, Coastal waters from Great Egg Inlet to\nCape May NJ out 20 nm and Coastal waters from Manasquan Inlet\nto Little Egg Inlet NJ out 20 nm.\n* WHEN...From 5 PM this afternoon to 3 AM EST Friday.\n* IMPACTS...Conditions will be hazardous to small craft.","tags": [ ]}] } -------------------------------------------------------------------------------- /SoftwareTests/RunAllTests.m: -------------------------------------------------------------------------------- 1 | function RunAllTests(ShowReport) 2 | arguments 3 | ShowReport (1,1) logical = false; 4 | end 5 | 6 | import matlab.unittest.plugins.TestReportPlugin; 7 | 8 | % Create a runner 9 | Runner = matlab.unittest.TestRunner.withTextOutput; 10 | Folder = fullfile(currentProject().RootFolder,"public",version("-release")); 11 | if ~isfolder(Folder) 12 | mkdir(Folder) 13 | else 14 | rmdir(Folder,'s') 15 | mkdir(Folder) 16 | end 17 | Plugin = TestReportPlugin.producingHTML(Folder,... 18 | "IncludingPassingDiagnostics",true,... 19 | "IncludingCommandWindowText",true,... 20 | "LoggingLevel",matlab.automation.Verbosity(1)); 21 | Runner.addPlugin(Plugin); 22 | 23 | 24 | % Create the test suite with SmokeTest and Function test if they exist 25 | Suite = testsuite("SmokeTests"); 26 | Suite = [Suite testsuite("FunctionTests")]; 27 | Suite = [Suite testsuite("SolnSmokeTests")]; 28 | 29 | % Run the test suite 30 | Results = Runner.run(Suite); 31 | 32 | if ShowReport 33 | web(fullfile(Folder,"index.html")) 34 | end 35 | 36 | % Format the results in a table and save them 37 | ResultsTable = table(Results') 38 | writetable(ResultsTable,fullfile(currentProject().RootFolder,... 39 | "public","TestResults_"+version("-release")+".txt")); 40 | 41 | % Assert success of test 42 | assertSuccess(Results); 43 | 44 | end 45 | -------------------------------------------------------------------------------- /SoftwareTests/SmokeTests.m: -------------------------------------------------------------------------------- 1 | classdef SmokeTests < matlab.unittest.TestCase 2 | 3 | properties 4 | RootFolder 5 | sparedEditors % Files already open when the test starts 6 | end % properties 7 | 8 | properties (ClassSetupParameter) 9 | Project = {currentProject()}; 10 | end % ClassSetupParameter 11 | 12 | properties (TestParameter) 13 | File; 14 | end % TestParameter 15 | 16 | methods (TestParameterDefinition,Static) 17 | 18 | function File = RetrieveFile(Project) %#ok 19 | % Retrieve student template files: 20 | RootFolder = currentProject().RootFolder; 21 | File = dir(fullfile(RootFolder,"Scripts","*.mlx")); 22 | File = {File.name}; 23 | end 24 | 25 | end % Static TestParameterDefinition 26 | 27 | methods (TestClassSetup) 28 | 29 | function SetUpSmokeTest(testCase,Project) %#ok 30 | % Navigate to project root folder: 31 | testCase.RootFolder = Project.RootFolder; 32 | cd(testCase.RootFolder) 33 | 34 | % Close the StartUp app if still open: 35 | delete(findall(groot,'Name','StartUp App')) 36 | 37 | % Log MATLAB version: 38 | testCase.log("Running in " + version) 39 | end 40 | 41 | end % TestClassSetup 42 | 43 | methods(TestMethodSetup) 44 | function recordEditorsToSpare(testCase) 45 | testCase.sparedEditors = matlab.desktop.editor.getAll; 46 | testCase.sparedEditors = {testCase.sparedEditors.Filename}; 47 | end 48 | end % TestMethodSetup 49 | 50 | methods(TestMethodTeardown) 51 | function closeOpenedEditors_thenDeleteWorkingDir(testCase) 52 | openEditors = matlab.desktop.editor.getAll; 53 | for editor=openEditors(1:end) 54 | if any(strcmp(editor.Filename, testCase.sparedEditors)) 55 | continue; 56 | end 57 | % if not on our list, close the file 58 | editor.close(); 59 | end 60 | end 61 | end % TestMethodTeardown 62 | 63 | methods(Test) 64 | 65 | function SmokeRun(testCase,File) 66 | 67 | % Navigate to project root folder: 68 | cd(testCase.RootFolder) 69 | FileToRun = string(File); 70 | 71 | % Pre-test: 72 | PreFiles = CheckPreFile(testCase,FileToRun); 73 | run(PreFiles); 74 | 75 | % Run SmokeTest 76 | disp(">> Running " + FileToRun); 77 | try 78 | run(fullfile("Scripts",FileToRun)); 79 | catch ME 80 | 81 | end 82 | 83 | % Post-test: 84 | PostFiles = CheckPostFile(testCase,FileToRun); 85 | run(PostFiles) 86 | 87 | % Log every figure created during run: 88 | Figures = findall(groot,'Type','figure'); 89 | Figures = flipud(Figures); 90 | if ~isempty(Figures) 91 | for f = 1:size(Figures,1) 92 | if ~isempty(Figures(f).Number) 93 | FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png'); 94 | log(testCase,1,FigDiag); 95 | end 96 | end 97 | end 98 | 99 | % Close all figures and Simulink models 100 | close all force 101 | if any(matlab.addons.installedAddons().Name == "Simulink") 102 | bdclose all 103 | end 104 | 105 | % Rethrow error if any 106 | if exist("ME","var") 107 | if ~any(strcmp(ME.identifier,KnownIssuesID)) 108 | rethrow(ME) 109 | end 110 | end 111 | 112 | end 113 | 114 | end % Test Methods 115 | 116 | 117 | methods (Access = private) 118 | 119 | function Path = CheckPreFile(testCase,Filename) 120 | PreFile = "Pre"+replace(Filename,".mlx",".m"); 121 | PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile); 122 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 123 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 124 | end 125 | if ~isfile(PreFilePath) 126 | writelines("% Pre-run script for "+Filename,PreFilePath) 127 | writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append'); 128 | writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append'); 129 | writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append'); 130 | writelines(" ",PreFilePath,'WriteMode','append'); 131 | end 132 | Path = PreFilePath; 133 | end 134 | 135 | function Path = CheckPostFile(testCase,Filename) 136 | PostFile = "Post"+replace(Filename,".mlx",".m"); 137 | PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile); 138 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 139 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 140 | end 141 | if ~isfile(PostFilePath) 142 | writelines("% Post-run script for "+Filename,PostFilePath) 143 | writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append'); 144 | writelines(" ",PostFilePath,'WriteMode','append'); 145 | end 146 | Path = PostFilePath; 147 | end 148 | 149 | end % Private Methods 150 | 151 | end % Smoketests -------------------------------------------------------------------------------- /SoftwareTests/SolnSmokeTests.m: -------------------------------------------------------------------------------- 1 | classdef SolnSmokeTests < matlab.unittest.TestCase 2 | 3 | properties 4 | RootFolder 5 | isSolnOnPath 6 | sparedEditors % Track open files 7 | end % properties 8 | 9 | properties (ClassSetupParameter) 10 | Project = {currentProject()}; 11 | end % ClassSetupParameter 12 | 13 | methods(TestMethodSetup) 14 | function recordEditorsToSpare(testCase) 15 | testCase.sparedEditors = matlab.desktop.editor.getAll; 16 | testCase.sparedEditors = {testCase.sparedEditors.Filename}; 17 | end 18 | end % TestMethodSetup 19 | 20 | methods(TestMethodTeardown) 21 | function closeOpenedEditors_thenDeleteWorkingDir(testCase) 22 | openEditors = matlab.desktop.editor.getAll; 23 | for editor=openEditors(1:end) 24 | if any(strcmp(editor.Filename, testCase.sparedEditors)) 25 | continue; 26 | end 27 | % if not on our list, close the file 28 | editor.close(); 29 | end 30 | end 31 | end % TestMethodTeardown 32 | 33 | properties (TestParameter) 34 | File; 35 | end % TestParameter 36 | 37 | methods (TestParameterDefinition,Static) 38 | 39 | function File = GetScriptName(Project) 40 | % Retrieve student template files: 41 | RootFolder = Project.RootFolder; 42 | File = dir(fullfile(RootFolder,"Scripts","*.mlx")); 43 | File = {File.name}; 44 | end 45 | 46 | end % Static TestParameterDefinition 47 | 48 | methods (TestClassSetup) 49 | 50 | function SetUpPath(testCase,Project) 51 | % Navigate to project root folder: 52 | testCase.RootFolder = Project.RootFolder; 53 | cd(testCase.RootFolder) 54 | 55 | % Check that solutions are on path: 56 | testCase.isSolnOnPath = isfolder("Solutions"); 57 | if testCase.isSolnOnPath == 0 58 | addpath(genpath(fullfile(testCase.RootFolder,"InstructorResources","Solutions"))) 59 | end 60 | 61 | % Close the StartUp app if still open: 62 | delete(findall(groot,'Name','StartUp App')) 63 | 64 | % Log MATLAB version: 65 | testCase.log("Running in " + version) 66 | 67 | end % function setUpPath 68 | 69 | end % methods (TestClassSetup) 70 | 71 | methods(Test) 72 | 73 | % Check that solutions files exist for each of the student 74 | % templates 75 | function ExistSolns(testCase,File) 76 | SolutionName = replace(string(File),".mlx","Soln.mlx"); 77 | assert(exist(SolutionName,"file"),"Missing solutions for "+File); 78 | end 79 | 80 | 81 | function SmokeRun(testCase,File) 82 | 83 | % Navigate to project root folder: 84 | cd(testCase.RootFolder) 85 | FileToRun = replace(string(File),".mlx","Soln.mlx"); 86 | 87 | % Pre-test: 88 | PreFiles = CheckPreFile(testCase,FileToRun); 89 | run(PreFiles); 90 | 91 | % Run SmokeTest 92 | disp(">> Running " + FileToRun); 93 | try 94 | run(fullfile("InstructorResources","Solutions",FileToRun)); 95 | catch ME 96 | 97 | end 98 | 99 | % Post-test: 100 | PostFiles = CheckPostFile(testCase,FileToRun); 101 | run(PostFiles) 102 | 103 | % Log every figure created during run: 104 | Figures = findall(groot,'Type','figure'); 105 | Figures = flipud(Figures); 106 | if ~isempty(Figures) 107 | for f = 1:size(Figures,1) 108 | if ~isempty(Figures(f).Number) 109 | FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png'); 110 | log(testCase,1,FigDiag); 111 | end 112 | end 113 | end 114 | 115 | % Close all figures and Simulink models 116 | close all force 117 | if any(matlab.addons.installedAddons().Name == "Simulink") 118 | bdclose all 119 | end 120 | 121 | % Rethrow error if any 122 | if exist("ME","var") 123 | if ~any(strcmp(ME.identifier,KnownIssuesID)) 124 | rethrow(ME) 125 | end 126 | end 127 | 128 | end 129 | 130 | end % Test Methods 131 | 132 | methods (Access = private) 133 | 134 | function Path = CheckPreFile(testCase,Filename) 135 | PreFile = "Pre"+replace(Filename,".mlx",".m"); 136 | PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile); 137 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 138 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles")) 139 | end 140 | if ~isfile(PreFilePath) 141 | writelines("% Pre-run script for "+Filename,PreFilePath) 142 | writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append'); 143 | writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append'); 144 | writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append'); 145 | writelines(" ",PreFilePath,'WriteMode','append'); 146 | end 147 | Path = PreFilePath; 148 | end 149 | 150 | function Path = CheckPostFile(testCase,Filename) 151 | PostFile = "Post"+replace(Filename,".mlx",".m"); 152 | PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile); 153 | if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 154 | mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles")) 155 | end 156 | if ~isfile(PostFilePath) 157 | writelines("% Post-run script for "+Filename,PostFilePath) 158 | writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append'); 159 | writelines(" ",PostFilePath,'WriteMode','append'); 160 | end 161 | Path = PostFilePath; 162 | end 163 | 164 | end % Private Access Methods 165 | 166 | methods (TestClassTeardown) 167 | 168 | function ResetPath(testCase) 169 | if ~testCase.isSolnOnPath && exist("Solutions","dir") 170 | rmpath(genpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions"))) 171 | end 172 | end 173 | 174 | end % TestClassTeardown 175 | 176 | end % SolnSmokeTests 177 | -------------------------------------------------------------------------------- /SoftwareTests/TestResults_R2023a.txt: -------------------------------------------------------------------------------- 1 | Name,Passed,Failed,Incomplete,Duration,Details 2 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CheckingTheWeather.mlx),1,0,0,8.2960691, 3 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CreateCurrentWeatherApp.mlx),1,0,0,0.0004901, 4 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=SampleWeatherDashboard.mlx),1,0,0,0.0004588, 5 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=UsingMATLABwithPython.mlx),1,0,0,2.2924885, 6 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=WeatherForecast.mlx),1,0,0,0.3437829, 7 | -------------------------------------------------------------------------------- /SoftwareTests/TestResults_R2024a.txt: -------------------------------------------------------------------------------- 1 | Name,Passed,Failed,Incomplete,Duration,Details 2 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CheckingTheWeather.mlx),1,0,0,0.1316994, 3 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CreateCurrentWeatherApp.mlx),1,0,0,0.0003877, 4 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=SampleWeatherDashboard.mlx),1,0,0,0.000197, 5 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=UsingMATLABwithPython.mlx),1,0,0,0.3888675, 6 | SmokeTests[Project=0x0_char]/SmokeRun(Scripts=WeatherForecast.mlx),1,0,0,0.0044386, 7 | -------------------------------------------------------------------------------- /Utilities/OldVersions/CheckingTheWeatherOld.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Utilities/OldVersions/CheckingTheWeatherOld.mlx -------------------------------------------------------------------------------- /Utilities/OldVersions/UsingMATLABwithPythonOld.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Utilities/OldVersions/UsingMATLABwithPythonOld.mlx -------------------------------------------------------------------------------- /Utilities/ProjectShutdown.m: -------------------------------------------------------------------------------- 1 | % Close the StartUp app if still open: 2 | delete(findall(groot,'Name','StartUp App')) -------------------------------------------------------------------------------- /Utilities/ProjectStartupApp.m: -------------------------------------------------------------------------------- 1 | classdef ProjectStartupApp < matlab.apps.AppBase 2 | 3 | % Properties that correspond to app components 4 | properties (Access = public) 5 | StartUpAppUIFigure matlab.ui.Figure 6 | TabGroup matlab.ui.container.TabGroup 7 | WelcomeTab matlab.ui.container.Tab 8 | Image matlab.ui.control.Image 9 | READMEButton matlab.ui.control.Button 10 | ReviewUsButton matlab.ui.control.Button 11 | MainMenuButton matlab.ui.control.Button 12 | WelcomeTitle matlab.ui.control.Label 13 | TabReview matlab.ui.container.Tab 14 | OtherButton matlab.ui.control.Button 15 | StudentButton matlab.ui.control.Button 16 | FacultyButton matlab.ui.control.Button 17 | Q1 matlab.ui.control.Label 18 | ReviewTitle matlab.ui.control.Label 19 | ReviewText matlab.ui.control.Label 20 | end 21 | 22 | 23 | properties (Access = private) 24 | GitHubOrganization = "MathWorks-Teaching-Resources"; % Description 25 | GitHubRepository = "Programming-A-Starter-Project-Using-MATLAB-and-Python"; 26 | end 27 | %% How to customize the app? 28 | %{ 29 | 30 | This StartUp app is designed to be customized to your module. It 31 | requires a minimum number of customization: 32 | 33 | 1. Change "Module Template" in app.WelcomeTitle by your module name 34 | 2. Change "Module Template" in app.ReviewTitle by your module name 35 | 3. Change the GitHubRepository (line 25) to the correct value 36 | 4. Change image in app.Image by the cover image you would like for your 37 | module. This image should be located in rootFolder/Images 38 | 5. Create your MS Form: 39 | a. Make a copy of the Faculty and the Student Template surveys 40 | b. Customize the name of the survey to match the name of your 41 | survey 42 | c. Click on "Collect responses", select "Anyone can respond" and 43 | copy the form link to SetupAppLinks (see step 6). 44 | 5. Create your MS Sway: 45 | a. Go to MS Sway 46 | b. Create a blank sway 47 | c. Add the name of your module to the title box 48 | d. Click "Share", Select "Anyone with a link", Select "View" 49 | e. Copy the sway link to SetupAppLinks (see step 6). 50 | 6. Add the Survey and Sway link to Utilities/SurveyLinks using 51 | SetupAppLinks.mlx in InternalFiles/RequiredFunctions/StartUpFcn 52 | 7. Save > Export to .m file and save the result as 53 | Utilities/ProjectStartupApp.m 54 | 55 | %} 56 | 57 | methods (Access = private, Static) 58 | 59 | function pingSway(app) 60 | try 61 | if ~ispref("MCCTEAM") 62 | load Utilities\SurveyLinks.mat SwayLink 63 | webread(SwayLink); 64 | end 65 | catch 66 | end 67 | end 68 | 69 | function openStudentForm(app) 70 | try 71 | load Utilities\SurveyLinks.mat StudentFormLink 72 | web(StudentFormLink); 73 | catch 74 | end 75 | end 76 | 77 | function openFacultyForm(app) 78 | try 79 | load Utilities\SurveyLinks.mat FacultyFormLink 80 | web(FacultyFormLink); 81 | catch 82 | end 83 | end 84 | 85 | function saveSettings(isReviewed,numLoad) 86 | try 87 | save(fullfile("Utilities","ProjectSettings.mat"),"isReviewed","numLoad"); 88 | catch 89 | end 90 | end 91 | 92 | end 93 | 94 | 95 | % Callbacks that handle component events 96 | methods (Access = private) 97 | 98 | % Code that executes after component creation 99 | function startupFcn(app) 100 | 101 | % Switch tab to review if has not been reviewed yet 102 | if isfile(fullfile("Utilities","ProjectSettings.mat")) 103 | load(fullfile("Utilities","ProjectSettings.mat"),"isReviewed","numLoad"); 104 | numLoad = numLoad + 1; % Increment counter 105 | else 106 | isReviewed = false; 107 | numLoad = 1; % Initialize counter 108 | end 109 | 110 | % Switch tab for review 111 | if ~isReviewed && numLoad > 2 112 | isReviewed = true; 113 | app.TabGroup.SelectedTab = app.TabReview; 114 | end 115 | 116 | % Save new settings 117 | app.saveSettings(isReviewed,numLoad) 118 | 119 | % Download links to survey (should only work when module goes 120 | % public on GitHub) 121 | try 122 | import matlab.net.* 123 | import matlab.net.http.* 124 | 125 | Request = RequestMessage; 126 | Request.Method = 'GET'; 127 | Address = URI("http://api.github.com/repos/"+app.GitHubOrganization+... 128 | "/"+app.GitHubRepository+"/contents/Utilities/SurveyLinks.mat"); 129 | Request.Header = HeaderField("X-GitHub-Api-Version","2022-11-28"); 130 | Request.Header(2) = HeaderField("Accept","application/vnd.github+json"); 131 | [Answer,~,~] = send(Request,Address); 132 | websave(fullfile("Utilities/SurveyLinks.mat"),Answer.Body.Data.download_url); 133 | catch 134 | end 135 | 136 | end 137 | 138 | % Close request function: StartUpAppUIFigure 139 | function StartUpAppUIFigureCloseRequest(app, event) 140 | if event.Source == app.READMEButton 141 | open README.mlx 142 | elseif event.Source == app.MainMenuButton 143 | open MainMenu.mlx 144 | elseif event.Source == app.FacultyButton 145 | open MainMenu.mlx 146 | elseif event.Source == app.StudentButton 147 | open MainMenu.mlx 148 | elseif event.Source == app.OtherButton 149 | open MainMenu.mlx 150 | else 151 | disp("Thank you for your time.") 152 | end 153 | delete(app) 154 | end 155 | 156 | % Button pushed function: MainMenuButton 157 | function MainMenuButtonPushed(app, event) 158 | StartUpAppUIFigureCloseRequest(app,event) 159 | end 160 | 161 | % Button pushed function: FacultyButton 162 | function FacultyButtonPushed(app, event) 163 | app.pingSway; 164 | app.openFacultyForm; 165 | StartUpAppUIFigureCloseRequest(app,event) 166 | end 167 | 168 | % Button pushed function: StudentButton 169 | function StudentButtonPushed(app, event) 170 | app.pingSway; 171 | app.openStudentForm; 172 | StartUpAppUIFigureCloseRequest(app,event) 173 | end 174 | 175 | % Button pushed function: OtherButton 176 | function OtherButtonPushed(app, event) 177 | app.pingSway; 178 | app.openStudentForm; 179 | StartUpAppUIFigureCloseRequest(app,event) 180 | end 181 | 182 | % Button pushed function: ReviewUsButton 183 | function ReviewUsButtonPushed(app, event) 184 | app.TabGroup.SelectedTab = app.TabReview; 185 | end 186 | 187 | % Button pushed function: READMEButton 188 | function READMEButtonPushed(app, event) 189 | StartUpAppUIFigureCloseRequest(app,event) 190 | end 191 | end 192 | 193 | % Component initialization 194 | methods (Access = private) 195 | 196 | % Create UIFigure and components 197 | function createComponents(app) 198 | 199 | % Create StartUpAppUIFigure and hide until all components are created 200 | app.StartUpAppUIFigure = uifigure('Visible', 'off'); 201 | app.StartUpAppUIFigure.AutoResizeChildren = 'off'; 202 | app.StartUpAppUIFigure.Position = [100 100 276 430]; 203 | app.StartUpAppUIFigure.Name = 'StartUp App'; 204 | app.StartUpAppUIFigure.Resize = 'off'; 205 | app.StartUpAppUIFigure.CloseRequestFcn = createCallbackFcn(app, @StartUpAppUIFigureCloseRequest, true); 206 | 207 | % Create TabGroup 208 | app.TabGroup = uitabgroup(app.StartUpAppUIFigure); 209 | app.TabGroup.AutoResizeChildren = 'off'; 210 | app.TabGroup.Position = [1 1 276 460]; 211 | 212 | % Create WelcomeTab 213 | app.WelcomeTab = uitab(app.TabGroup); 214 | app.WelcomeTab.AutoResizeChildren = 'off'; 215 | app.WelcomeTab.Title = 'Tab'; 216 | 217 | % Create WelcomeTitle 218 | app.WelcomeTitle = uilabel(app.WelcomeTab); 219 | app.WelcomeTitle.HorizontalAlignment = 'center'; 220 | app.WelcomeTitle.VerticalAlignment = 'top'; 221 | app.WelcomeTitle.WordWrap = 'on'; 222 | app.WelcomeTitle.FontSize = 24; 223 | app.WelcomeTitle.FontWeight = 'bold'; 224 | app.WelcomeTitle.Position = [2 330 274 89]; 225 | app.WelcomeTitle.Text = 'Programming: A Starter Project Using MATLAB with Python'; 226 | 227 | % Create MainMenuButton 228 | app.MainMenuButton = uibutton(app.WelcomeTab, 'push'); 229 | app.MainMenuButton.ButtonPushedFcn = createCallbackFcn(app, @MainMenuButtonPushed, true); 230 | app.MainMenuButton.FontSize = 18; 231 | app.MainMenuButton.Position = [59 96 161 35]; 232 | app.MainMenuButton.Text = 'Main Menu'; 233 | 234 | % Create ReviewUsButton 235 | app.ReviewUsButton = uibutton(app.WelcomeTab, 'push'); 236 | app.ReviewUsButton.ButtonPushedFcn = createCallbackFcn(app, @ReviewUsButtonPushed, true); 237 | app.ReviewUsButton.FontSize = 18; 238 | app.ReviewUsButton.Position = [59 10 161 35]; 239 | app.ReviewUsButton.Text = 'Review Us'; 240 | 241 | % Create READMEButton 242 | app.READMEButton = uibutton(app.WelcomeTab, 'push'); 243 | app.READMEButton.ButtonPushedFcn = createCallbackFcn(app, @READMEButtonPushed, true); 244 | app.READMEButton.FontSize = 18; 245 | app.READMEButton.Position = [59 53 161 35]; 246 | app.READMEButton.Text = 'README'; 247 | 248 | % Create Image 249 | app.Image = uiimage(app.WelcomeTab); 250 | app.Image.Position = [21 137 235 186]; 251 | app.Image.ImageSource = 'windTokyo.gif'; 252 | 253 | % Create TabReview 254 | app.TabReview = uitab(app.TabGroup); 255 | app.TabReview.AutoResizeChildren = 'off'; 256 | app.TabReview.Title = 'Tab2'; 257 | app.TabReview.HandleVisibility = 'off'; 258 | 259 | % Create ReviewText 260 | app.ReviewText = uilabel(app.TabReview); 261 | app.ReviewText.HorizontalAlignment = 'center'; 262 | app.ReviewText.VerticalAlignment = 'top'; 263 | app.ReviewText.WordWrap = 'on'; 264 | app.ReviewText.FontSize = 18; 265 | app.ReviewText.Position = [16 243 245 69]; 266 | app.ReviewText.Text = 'Please help us improve your experience by answering a few questions.'; 267 | 268 | % Create ReviewTitle 269 | app.ReviewTitle = uilabel(app.TabReview); 270 | app.ReviewTitle.HorizontalAlignment = 'center'; 271 | app.ReviewTitle.VerticalAlignment = 'top'; 272 | app.ReviewTitle.WordWrap = 'on'; 273 | app.ReviewTitle.FontSize = 24; 274 | app.ReviewTitle.FontWeight = 'bold'; 275 | app.ReviewTitle.Position = [2 326 274 93]; 276 | app.ReviewTitle.Text = 'Programming: A Starter Project Using MATLAB with Python'; 277 | 278 | % Create Q1 279 | app.Q1 = uilabel(app.TabReview); 280 | app.Q1.HorizontalAlignment = 'center'; 281 | app.Q1.VerticalAlignment = 'top'; 282 | app.Q1.WordWrap = 'on'; 283 | app.Q1.FontSize = 18; 284 | app.Q1.FontWeight = 'bold'; 285 | app.Q1.Position = [16 141 245 69]; 286 | app.Q1.Text = 'What describes you best?'; 287 | 288 | % Create FacultyButton 289 | app.FacultyButton = uibutton(app.TabReview, 'push'); 290 | app.FacultyButton.ButtonPushedFcn = createCallbackFcn(app, @FacultyButtonPushed, true); 291 | app.FacultyButton.FontSize = 18; 292 | app.FacultyButton.Position = [64 127 150 40]; 293 | app.FacultyButton.Text = 'Faculty'; 294 | 295 | % Create StudentButton 296 | app.StudentButton = uibutton(app.TabReview, 'push'); 297 | app.StudentButton.ButtonPushedFcn = createCallbackFcn(app, @StudentButtonPushed, true); 298 | app.StudentButton.FontSize = 18; 299 | app.StudentButton.Position = [64 80 150 40]; 300 | app.StudentButton.Text = 'Student'; 301 | 302 | % Create OtherButton 303 | app.OtherButton = uibutton(app.TabReview, 'push'); 304 | app.OtherButton.ButtonPushedFcn = createCallbackFcn(app, @OtherButtonPushed, true); 305 | app.OtherButton.FontSize = 18; 306 | app.OtherButton.Position = [64 34 150 40]; 307 | app.OtherButton.Text = 'Other'; 308 | 309 | % Show the figure after all components are created 310 | app.StartUpAppUIFigure.Visible = 'on'; 311 | end 312 | end 313 | 314 | % App creation and deletion 315 | methods (Access = public) 316 | 317 | % Construct app 318 | function app = ProjectStartupApp 319 | 320 | % Create UIFigure and components 321 | createComponents(app) 322 | 323 | % Register the app with App Designer 324 | registerApp(app, app.StartUpAppUIFigure) 325 | 326 | % Execute the startup function 327 | runStartupFcn(app, @startupFcn) 328 | 329 | if nargout == 0 330 | clear app 331 | end 332 | end 333 | 334 | % Code that executes before app deletion 335 | function delete(app) 336 | 337 | % Delete UIFigure when app is deleted 338 | delete(app.StartUpAppUIFigure) 339 | end 340 | end 341 | end -------------------------------------------------------------------------------- /Utilities/SurveyLinks.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python/dc3d99fe7fb71628e1c30fdd08ac4320d3dc0f55/Utilities/SurveyLinks.mat -------------------------------------------------------------------------------- /resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/QEd0x6jBcKf03RgXQ3y07QAWBCsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/QEd0x6jBcKf03RgXQ3y07QAWBCsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/_kanDHLwZvrSM1wrb2rL3R-TtpAd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/_kanDHLwZvrSM1wrb2rL3R-TtpAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/b4fK1nwNVcMFfH2HWk_9bHC2cXcd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/b4fK1nwNVcMFfH2HWk_9bHC2cXcp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/-Yp4iI7AkN0RXWsqH_qBv8BSoUsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/-Yp4iI7AkN0RXWsqH_qBv8BSoUsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/5wkpcXVsAhrdVuZJuRCjlxSek_Yd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/5wkpcXVsAhrdVuZJuRCjlxSek_Yp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/897K1ZIAIxWZa69h7rzaFEkJJ1Yd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/897K1ZIAIxWZa69h7rzaFEkJJ1Yp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/LUM1KVG-kpiMYV7i1xDItZmUkVQd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/LUM1KVG-kpiMYV7i1xDItZmUkVQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/SGHsdnqYqyGyYGQP-0wqh6AyERAd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/SGHsdnqYqyGyYGQP-0wqh6AyERAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/TzEa1ML1Hz49sPNQX5JM6EE413Qd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/TzEa1ML1Hz49sPNQX5JM6EE413Qp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Ur1esh7xN9L6aqDUKBE31DKE1Qod.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/Ur1esh7xN9L6aqDUKBE31DKE1Qop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/VnvWkijFxdp8LV3ck_Qpq9eyOpMd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/VnvWkijFxdp8LV3ck_Qpq9eyOpMp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/WNBzWWmVwu8nwCU7p01ZJtQ5j-od.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/WNBzWWmVwu8nwCU7p01ZJtQ5j-op.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/gK0bzvM8fEYFwItc078tqn4EOmId.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/gK0bzvM8fEYFwItc078tqn4EOmIp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h026LEbG6ImfsgAII1WcSM9Hnnod.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h026LEbG6ImfsgAII1WcSM9Hnnop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/nA_28eBnx5NCFw_vQVWFh5ohqUAd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/nA_28eBnx5NCFw_vQVWFh5ohqUAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/w234j28OzyIgK86-1WWW6oJ1rp4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/w234j28OzyIgK86-1WWW6oJ1rp4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/xH29tmOwPG1ix8h2YNwMHPQ_-ukd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BT5hWoz-UTefONdqForZyI91O8Y/xH29tmOwPG1ix8h2YNwMHPQ_-ukp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/AHoLGOV6JxAa3mDfXPOye2W3psUd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/AHoLGOV6JxAa3mDfXPOye2W3psUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/NvNsziUvXU2FO5oXU12jeMmASEwd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/NvNsziUvXU2FO5oXU12jeMmASEwp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/dxW0rLxFMXm0cpQGCSkWQRi2YRsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/BjxNC43HIPP8KZwg_cceb68ikkA/dxW0rLxFMXm0cpQGCSkWQRi2YRsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/_8KD0FwxV6biv7mEQTGecP1TTPgd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/_8KD0FwxV6biv7mEQTGecP1TTPgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/2kj09UetkV_lru3gvSPXnY6-nM4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/2kj09UetkV_lru3gvSPXnY6-nM4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/KKyDJtbdIBOlaeHmIZd5VX6vqx8d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/KKyDJtbdIBOlaeHmIZd5VX6vqx8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/QWNDYJD5mGW1bWYvPx9DtKnxzw4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/QWNDYJD5mGW1bWYvPx9DtKnxzw4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/R1RggVhA72agIvELiuhWPRS8F0Id.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/R1RggVhA72agIvELiuhWPRS8F0Ip.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/aEHSZBIY-yve10yGis12Zr5DLZod.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/aEHSZBIY-yve10yGis12Zr5DLZop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/j4xwF_j8iFTVayUMfxLgMnTbencd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/j4xwF_j8iFTVayUMfxLgMnTbencp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/r8LR4nLmg9ai3oHrW1r_-KocQzkd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/r8LR4nLmg9ai3oHrW1r_-KocQzkp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/EyDhXb-HjEIhAYfuSMUxquCH4aYd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/EyDhXb-HjEIhAYfuSMUxquCH4aYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/d1u4eIKNgMuS21WRxXrD0UScuR8d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/d1u4eIKNgMuS21WRxXrD0UScuR8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gjXMbSOzqQJbg7H7bMF0OVGji80d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gjXMbSOzqQJbg7H7bMF0OVGji80p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/p5HYYVUpTuYgZwnT8QkkzaoJraUd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/p5HYYVUpTuYgZwnT8QkkzaoJraUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/q4FWbcu8zEbneDjWzNwfvfvjQNAd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/q4FWbcu8zEbneDjWzNwfvfvjQNAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/s-04wUzHjOhlMa1CW_zpJwm8iDMd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/s-04wUzHjOhlMa1CW_zpJwm8iDMp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/IeTljmmsHd59nip38CQ5y5dOQnQd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/IeTljmmsHd59nip38CQ5y5dOQnQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/QOpe-1pctdftDIjwQLRdjOUZW44d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/QOpe-1pctdftDIjwQLRdjOUZW44p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/bzMXcEpQelehv3qzHYr9ceCGgIod.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/bzMXcEpQelehv3qzHYr9ceCGgIop.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/hy3T897OVbl4TCaWFBnKRKDU0M8d.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/hy3T897OVbl4TCaWFBnKRKDU0M8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/fjRQtWiSIy7hIlj-Kmk87M7s21k/NjSPEMsIuLUyIpr2u1Js5bVPsOsd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/fjRQtWiSIy7hIlj-Kmk87M7s21k/NjSPEMsIuLUyIpr2u1Js5bVPsOsp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/RMvf4mEDuznAOqU6SKNmIWErfxgd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/RMvf4mEDuznAOqU6SKNmIWErfxgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/ZTr3GAe6p03ZVs2FdKKE0JsiFMQd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/ZTr3GAe6p03ZVs2FdKKE0JsiFMQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/uIbyU9dPEHKvxjdwx5pD9PDDCZYd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/uIbyU9dPEHKvxjdwx5pD9PDDCZYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/2zjcQkVJSJ_AwC9M8R9BTSESRzcd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/2zjcQkVJSJ_AwC9M8R9BTSESRzcp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BT5hWoz-UTefONdqForZyI91O8Yd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BT5hWoz-UTefONdqForZyI91O8Yp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BjxNC43HIPP8KZwg_cceb68ikkAd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/BjxNC43HIPP8KZwg_cceb68ikkAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/KocSmEw1PpelhlG7ZNeMUdHVtywd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/KocSmEw1PpelhlG7ZNeMUdHVtywp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/QMJD9OLFzxcTTbPOoh-ahQ4zTRUd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/QMJD9OLFzxcTTbPOoh-ahQ4zTRUp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/R0IsxKENiOKovWZXASFjrmpbBCYd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/R0IsxKENiOKovWZXASFjrmpbBCYp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/ZN2RlSIbyWXhOxbxxI4hOawbMD4d.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/ZN2RlSIbyWXhOxbxxI4hOawbMD4p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/ZdVxxv9BsNz7MGUxtEc6Pq3qh1Md.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/ZdVxxv9BsNz7MGUxtEc6Pq3qh1Mp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/iMwdHOXOBiBXhnA_li8gtEJVTjcd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/iMwdHOXOBiBXhnA_li8gtEJVTjcp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rh0jHbNfmojECiiHH7BQHmZTsWkd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rh0jHbNfmojECiiHH7BQHmZTsWkp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rnpMu7jn2QWt_rQcz8FJ-MxGzVId.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/rnpMu7jn2QWt_rQcz8FJ-MxGzVIp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/trBOSMFt-ZFz0tI8PrpBhVjGM5Md.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/trBOSMFt-ZFz0tI8PrpBhVjGM5Mp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/6x1BhZX_fLnKpcwqra0qFwv1jIgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/EEtUlUb-dLAdf0KpMVivaUlztwAp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/HoHDHQ_WvHAAKj5aJOrvrg_vpt8p.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/KAXfQgCar2Yb8zOxgvf9hdmLP1Ep.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/NmGqIpAwUJcXFyLjFAGnU9uyN5Yp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/WZRuNzqc-Db7NcQAZO8Y-R8U9ccp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/fjRQtWiSIy7hIlj-Kmk87M7s21kp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/root/qaw0eS1zuuY1ar9TdPn1GMfrjbQp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/rootp.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/uuid-0192afd8-7310-46b8-ad07-aacb330fc399.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /resources/project/uuid-366ca619-578a-4bc0-8012-bfa62d28c37f.xml: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------