diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b01ed31..fa2450b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,16 +8,24 @@ on:
branches: [ release ]
workflow_dispatch:
+# Add permission to write GitHub pages
+permissions:
+ contents: write
+ pages: write
+ id-token: write
+
jobs:
test:
strategy:
fail-fast: false
matrix:
- MATLABVersion: [R2023b,R2024a]
+ MATLABVersion: [R2024b,R2025a,R2025b]
runs-on: ubuntu-latest
+ env:
+ LD_PRELOAD: /usr/lib/x86_64-linux-gnu/libstdc++.so.6
steps:
# Checks-out your repository
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Sets up a display server
- name: Start display server
@@ -32,9 +40,17 @@ jobs:
uses: matlab-actions/setup-matlab@v2
with:
release: ${{ matrix.MATLABVersion }}
- products: Symbolic_Math_Toolbox
+ products: >
+ Symbolic_Math_Toolbox
# Simulink Statistics_and_Machine_Learning_Toolbox
# List required products above in the format shown (and uncomment them)
+ # List of product strings:
+ # Simulink
+ # Statistics_and_Machine_Learning_Toolbox
+ # Simulink_Coder
+ # Econometrics_Toolbox
+ # Deep_Learning_Toolbox
+
# Run all the tests
- name: Run SmokeTests
@@ -44,10 +60,12 @@ jobs:
# Upload the test results as artifact
- name: Upload TestResults
- uses: actions/upload-artifact@v3.1.3
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v4
with:
- name: TestResults
- path: ./SoftwareTests/TestResults_${{ matrix.MATLABVersion }}.txt
+ name: TestResults_${{ matrix.MATLABVersion }}
+ path: ./public/*
+ overwrite: true
badge:
if: ${{ always() }}
@@ -58,26 +76,38 @@ jobs:
steps:
# Checks-out your repository
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
# Sets up R2023b
- name: Setup MATLAB
uses: matlab-actions/setup-matlab@v2
with:
- release: R2023b
+ release: R2024b
# Download the test results from artifact
- - name: Download TestResults
- uses: actions/download-artifact@v2.1.1
+ - name: Download All TestResults
+ uses: actions/download-artifact@v4
with:
- name: TestResults
- path: ./SoftwareTests/
-
+ path: public
+ pattern: TestResults_*
+ merge-multiple: true
+
# Create the test results badge
- - name: Run CreateBadge
+ - name: Run PostSmokeTest
uses: matlab-actions/run-command@v2
with:
- command: openProject(pwd); CreateBadge;
+ command: openProject(pwd); PostSmokeTest;
+
+ # Deploy reports to GitHub pages
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+ - name: Upload pages artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: public
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
# Commit the JSON for the MATLAB releases badge
- name: Commit changed files
@@ -85,8 +115,6 @@ jobs:
run: |
git config user.name "${{ github.workflow }} by ${{ github.actor }}"
git config user.email "<>"
- git pull
git add Images/TestedWith.json
git commit Images/TestedWith.json -m "Update CI badges ${{ github.ref_name }}"
- git fetch
git push
diff --git a/.gitignore b/.gitignore
index aef55c1..14f9f76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,4 @@
# List of untracked files to ignore
-*.vs
-
-# Prevent accidentally committing your API key
-myAPIkey.txt
-
-# Live Task Repository
-MATLAB-Live-Task-for-Python
# Autosave files
*.asv
@@ -13,6 +6,9 @@ MATLAB-Live-Task-for-Python
*.autosave
*.slx.r*
*.mdl.r*
+__pycache__
+*.pyc
+*/*.pyc
# MATLAB Drive
*.MATLABDriveTag
@@ -47,9 +43,6 @@ codegen/
*.elf
*.hex
*.bin
-__pycache__
-*.pyc
-*/*.pyc
# Cache files
*.slxc
@@ -57,8 +50,12 @@ __pycache__
# Project settings
Utilities/ProjectSettings.mat
-# Test results
-SoftwareTests/TestResults_*
-
# GitLab page folder
public/
+
+# Prevent accidentally committing your API key
+myAPIkey.txt
+
+# Live Task Repository
+MATLAB-Live-Task-for-Python
+
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 8d2d7db..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,98 +0,0 @@
-stages:
-# Set up two testing paths
- - setup
- - test
- - deploy
- - release
-
-setup-job:
- tags:
- - matlab
- stage: setup
- script:
- - cd ..
- - if (test-path utilities) { rm -r -force utilities }
- - git clone git@insidelabs-git.mathworks.com:modular-curriculum-content/utilities.git
- - cd $CI_PROJECT_NAME
- allow_failure: false
-
-
-smoke-test:
-# Smoke tests should run all the time
- tags:
- # Add additional tags like (e.g. - arduino) as required
- # Make sure that the runner you plan to use matches the tags
- - matlab
- stage: test
- script:
- - matlab -batch "openProject(pwd);RunAllTests(true)"
- when: always
- allow_failure: true
- artifacts:
- paths:
- - public/*
- expire_in: 1 years
-
-pages:
- tags:
- - matlab
- stage: deploy
- script:
- - echo 'Deploying pages'
- artifacts:
- paths:
- - public
-
-smoke-test-solution:
- tags:
- - matlab
- stage: release
- script:
- - matlab -batch "proj = openProject(pwd);
- addpath(genpath(proj.RootFolder));
- results = runtests(fullfile('InternalFiles','Tests','CI','SolnSmokeTests.m'));
- disp(table(results)); assertSuccess(results);"
- rules:
-# This test should always run when merging to main
-# And be available for manual running on any push
- - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
- when: always
- - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
- when: manual
- allow_failure: true
-
-file-test:
- tags:
- - matlab
- stage: release
- script:
- - matlab -batch "proj = openProject(pwd);
- addpath(proj.RootFolder+'/InternalFiles/Tests/CI');
- results = runtests('OpenCloseFileTest.m');
- disp(table(results)); assertSuccess(results);"
- rules:
-# This test should always run when merging to main
-# And be available for manual running on any push
- - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
- when: always
- - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
- when: manual
- allow_failure: true
-
-release-testing:
- tags:
- - matlab
- stage: release
- script:
- - matlab -batch "proj = openProject(pwd);
- cd ..;
- addpath(genpath(fullfile('utilities','TestingResources')));
- runCMTests"
- rules:
-# This test should always run when merging to main
-# And be available for manual running on any push
- - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
- when: always
- - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
- when: manual
- allow_failure: true
diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json
deleted file mode 100644
index f8b4888..0000000
--- a/.vs/ProjectSettings.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "CurrentProjectSetting": null
-}
\ No newline at end of file
diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite
deleted file mode 100644
index 53d9b1b..0000000
Binary files a/.vs/slnx.sqlite and /dev/null differ
diff --git a/FunctionLibrary/.gitkeep b/FunctionLibrary/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/FunctionLibrary/CheckPythonVersion.mlx b/FunctionLibrary/CheckPythonVersion.mlx
index 8095c4b..b5e0ab7 100644
Binary files a/FunctionLibrary/CheckPythonVersion.mlx and b/FunctionLibrary/CheckPythonVersion.mlx differ
diff --git a/Images/image_6.png b/Images/MouseThoughtBubble.png
similarity index 100%
rename from Images/image_6.png
rename to Images/MouseThoughtBubble.png
diff --git a/Images/image_9.png b/Images/RGBTurkeys.png
similarity index 100%
rename from Images/image_9.png
rename to Images/RGBTurkeys.png
diff --git a/Images/image_12.png b/Images/SeaSurfaceTemps.png
similarity index 100%
rename from Images/image_12.png
rename to Images/SeaSurfaceTemps.png
diff --git a/Images/TestedWith.json b/Images/TestedWith.json
index 61fdf9a..7e7e1c0 100644
--- a/Images/TestedWith.json
+++ b/Images/TestedWith.json
@@ -1 +1 @@
-{"schemaVersion":1,"label":"Tested with","color":"success","message":"R2023b | R2024a"}
+{"schemaVersion":1,"label":"Test Status","color":"success","message":"R2024b | R2025a | R2025b"}
diff --git a/Images/image_5.png b/Images/WeatherDashboard.png
similarity index 100%
rename from Images/image_5.png
rename to Images/WeatherDashboard.png
diff --git a/Images/image_4.png b/Images/WeatherStruct.png
similarity index 100%
rename from Images/image_4.png
rename to Images/WeatherStruct.png
diff --git a/InstructorResources/Solutions/CheckingTheWeatherSoln.mlx b/InstructorResources/Solutions/CheckingTheWeatherSoln.mlx
new file mode 100644
index 0000000..c81f902
Binary files /dev/null and b/InstructorResources/Solutions/CheckingTheWeatherSoln.mlx differ
diff --git a/InstructorResources/Solutions/CreateCurrentWeatherAppSoln.mlx b/InstructorResources/Solutions/CreateCurrentWeatherAppSoln.mlx
new file mode 100644
index 0000000..acb7550
Binary files /dev/null and b/InstructorResources/Solutions/CreateCurrentWeatherAppSoln.mlx differ
diff --git a/InstructorResources/Solutions/UsingMATLABwithPythonSoln.mlx b/InstructorResources/Solutions/UsingMATLABwithPythonSoln.mlx
new file mode 100644
index 0000000..f286f6c
Binary files /dev/null and b/InstructorResources/Solutions/UsingMATLABwithPythonSoln.mlx differ
diff --git a/MainMenu.mlx b/MainMenu.mlx
index dc07f4c..d9f6355 100644
Binary files a/MainMenu.mlx and b/MainMenu.mlx differ
diff --git a/README.md b/README.md
index 75c9acc..f2b2f91 100644
--- a/README.md
+++ b/README.md
@@ -1,144 +1,117 @@
-
-
-
-# Programming: A Starter Project Using MATLAB with Python
-
-
-[](https://www.mathworks.com/matlabcentral/fileexchange/116490-programming-a-starter-project-using-matlab-and-python) or [](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj)
-
-
-
-**Curriculum Module**
-
-_Created with R2022a. Compatible with R2022a and later releases._
-
-# Information
-
-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.
-
-# Prerequisite Domain Knowledge
-
-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).
-
-
-
-## Background
-
-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.
-
-
-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 Stop button in the **RUN** section of the **Live Editor** tab in the MATLAB Toolstrip.
-
-## Contact Us
-
-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.
-
-
-
-## Prerequisites
-
-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).
-
-
-
-## Getting Started
-### Accessing the Module
-### **On MATLAB Online:**
-
-Use the [ ](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.
-
-### **On Desktop:**
-
-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). It will add the appropriate files to your MATLAB path and open an app that asks you where you would like to start.
-
-
-Ensure you have all the required products ([listed below](#H_E850B4FF)) 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 **Add-Ons** > **Get Add-Ons**.
-
-
-
-## Products
-
-MATLAB® is used throughout. Tools from the Symbolic Math Toolbox™ are used to convert between different unit systems in the weather applications.
-
-
-
-# Scripts
-
- *If you are viewing this in a version of MATLAB prior to R2023b, you can view the learning outcomes for each script* [*here*](https://github.com/MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python)*.*
-
-
-
-## [**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=UsingMATLABwithPython.mlx)
-| **Introductory script** | **In this script, students will...** |
-| :-- | :-- |
-| | - check that an appropriate version of Python is installed and visible within MATLAB - explore the Run Python Code Live Task - try running Python commands and a Python script from MATLAB |
-
-
-
-## [**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=CheckingTheWeather.mlx)
-| **Investigatory script** | **In this script, students will...** |
-| :-- | :-- |
-| | - set up an account with OpenWeather to create your own API key - use existing Python code to make an API call to OpenWeather - use MATLAB to explore the data returned by the API call, including data type conversions and unit conversions |
-
-
-
-## [**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=CreateCurrentWeatherApp.mlx)
-| **Application script** | **In this script, students will...** |
-| :-- | :-- |
-| | - use App Designer to build a custom app using the code from CheckingTheWeather.mlx - create callbacks, properties, and functions - design and organize a UI with drag and drop elements - reuse code from CheckingTheWeather in a new context |
-
-
-
-# Apps
-
-Both of these apps require running Python from MATLAB, as set up in [UsingMATLABwithPython](#H_00FC9291) and an OpenWeather API key, as set up in [CheckingTheWeather](#H_39C74124).
-
-- **CurrentWeatherAppDemo.mlapp ** shows the results of working through CreateCurrentWeatherApp.
-- **WeatherDisplay.mlapp ** shows one elaborated version of the basic current weather app.
-
-
-# Additional Scripts
-
-For those with a legacy OpenWeather API key, or the willingness to sign up for the OneCall 3.0 API, the original weather forecasting exploration from this courseware module is included as well.
-
-
-[WeatherForecast.mlx](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=WeatherForecast.mlx)
-
-
-[SampleWeatherDashboard.mlx](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Programming-A-Starter-Project-Using-MATLAB-and-Python&project=MATLABwithPython.prj&file=SampleWeatherDashboard.mlx)
-
-
-
-# License
-
-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).
-
-
-
-# Related Courseware Modules
-| **Courseware Module** | **Sample Content** | **Available on:** |
-| :-- | :-- | :-- |
-| [**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 | | [ ](https://www.mathworks.com/matlabcentral/fileexchange/103225-fundamentals-of-programming) [ ](http://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) |
-| [**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 | | [ ](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code) [ ](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) |
-| [**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 | | [ ](https://www.mathworks.com/matlabcentral/fileexchange/115900-programming-organizing-data) [ ](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) |
-
-
-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).
-
-# Educator Resources
-- [Educator Page](https://www.mathworks.com/academia/educators.html)
-
-
-# Contribute
-
-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.
-
-# Acknowledgements
-
-Many thanks to Blake Naccarato on his suggestions for improvement.
-
-
- *©* Copyright 2024 The MathWorks™, Inc
-
-
-
+
+# Programming: A Starter Project Using MATLAB with Python
+
+Learn how to call Python code, convert data types and units, and use App Designer to build an app to display your results.
+
+[](https://www.mathworks.com/matlabcentral/fileexchange/116490-programming-a-starter-project-using-matlab-and-python) or [](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)
+
+[](https://MathWorks-Teaching-Resources.github.io/Programming-A-Starter-Project-Using-MATLAB-and-Python)
+
+**Curriculum Module**
+
+_Created with R2024a. Compatible with R2024a and later releases._
+
+# Information
+
+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.
+
+# Prerequisite Domain Knowledge
+
+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).
+
+
+## Background
+
+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.
+
+
+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 Stop button in the **RUN** section of the **Live Editor** tab in the MATLAB Toolstrip.
+
+## Contact Us
+
+Contact the [MathWorks Educator Content Development Team](mailto:onlineteaching@mathworks.com) if you would like to request assistance, provide feedback, or if you have a question.
+
+
+## Prerequisites
+
+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).
+
+
+## Getting Started
+### Accessing the Module
+### **On MATLAB Online:**
+
+Use the [ ](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.
+
+### **On Desktop:**
+
+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.
+
+
+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 **Add-Ons** > **Get Add-Ons**.
+
+
+## Products
+
+MATLAB® is used throughout. Tools from the Symbolic Math Toolbox™ are used to convert between different unit systems in the weather applications.
+
+# Scripts
+## [**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)
+| | |
+| :-- | :-- |
+| **Introductory script** | **In this script, students will...** |
+| | $\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 |
+| | |
+
+## [**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)
+| | |
+| :-- | :-- |
+| **Investigatory script** | **In this script, students will...** |
+| | $\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 |
+| | |
+
+## [**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)
+| | |
+| :-- | :-- |
+| **Application script** | **In this script, students will...** |
+| | $\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 |
+| | |
+
+# Apps
+
+Both of these apps require running Python from MATLAB, as set up in UsingMATLABwithPython and an OpenWeather API key, as set up in CheckingTheWeather.
+
+- **CurrentWeatherAppDemo.mlapp ** shows the results of working through CreateCurrentWeatherApp.
+- **WeatherDisplay.mlapp ** shows one elaborated version of the basic current weather app.
+
+# License
+
+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).
+
+# Related Courseware Modules
+| | | |
+| :-- | :-- | :-- |
+| **Courseware Module** | **Sample Content** | **Available on:** |
+| [**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 | | [ ](https://www.mathworks.com/matlabcentral/fileexchange/103225-fundamentals-of-programming) [ ](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) |
+| [**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 | | [ ](https://www.mathworks.com/matlabcentral/fileexchange/115905-programming-structuring-code) [ ](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) |
+| [**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 | | [ ](https://www.mathworks.com/matlabcentral/fileexchange/115900-programming-organizing-data) [ ](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) |
+| | | |
+
+
+Or feel free to explore our other [modular courseware content](https://www.mathworks.com/matlabcentral/fileexchange/?q=author%3A%22MathWorks+Educator+Content+Development+Team%22&sort=relevancy).
+
+# Educator Resources
+- [Educator Page](https://www.mathworks.com/academia/educators.html)
+
+# Contribute
+
+Looking for more? Find an issue? Have a suggestion? Please contact the [MathWorks Educator Content Development 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.
+
+# Acknowledgments
+
+Many thanks to Blake Naccarato on his suggestions for improvement.
+
+
+*©* Copyright 2025 The MathWorks, Inc
+
+
diff --git a/README.mlx b/README.mlx
index aa6043b..63575f7 100644
Binary files a/README.mlx and b/README.mlx differ
diff --git a/Scripts/CheckingTheWeather.mlx b/Scripts/CheckingTheWeather.mlx
index a3b54c9..f6e122f 100644
Binary files a/Scripts/CheckingTheWeather.mlx and b/Scripts/CheckingTheWeather.mlx differ
diff --git a/Scripts/CreateCurrentWeatherApp.mlx b/Scripts/CreateCurrentWeatherApp.mlx
index bff8f18..8411010 100644
Binary files a/Scripts/CreateCurrentWeatherApp.mlx and b/Scripts/CreateCurrentWeatherApp.mlx differ
diff --git a/Scripts/SampleWeatherDashboard.mlx b/Scripts/SampleWeatherDashboard.mlx
deleted file mode 100644
index 1ddefd8..0000000
Binary files a/Scripts/SampleWeatherDashboard.mlx and /dev/null differ
diff --git a/Scripts/UsingMATLABwithPython.mlx b/Scripts/UsingMATLABwithPython.mlx
index 88e7002..9a5db69 100644
Binary files a/Scripts/UsingMATLABwithPython.mlx and b/Scripts/UsingMATLABwithPython.mlx differ
diff --git a/Scripts/WeatherForecast.mlx b/Scripts/WeatherForecast.mlx
deleted file mode 100644
index 75489ca..0000000
Binary files a/Scripts/WeatherForecast.mlx and /dev/null differ
diff --git a/Scripts/checkweather.py b/Scripts/checkweather.py
deleted file mode 100644
index 307fc43..0000000
--- a/Scripts/checkweather.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-Python 3.8 code
-Created on Thu Jan 4 20:41:45 2018
-Modified May 2022
-
-@author: Heather Gorr
-Updated by: Emma Smith Zbarsky
-Copyright 2018-2022 The MathWorks, Inc.
-
-Create the Openweather API-structured URL using One Call
-as described in the documentation
-https://openweathermap.org/api/one-call-api
-This API is licensed under CC BY-SA 4.0, as documented here:
-https://creativecommons.org/licenses/by-sa/4.0/
-'''
-
-# checkweather.py
-import datetime
-import json
-import urllib.request
-
-BASE_URL = 'http://api.openweathermap.org/data/3.0/onecall?lat={}&lon={}&exclude=minutely,daily,alerts&units={}&appid={}'
-
-def get_weather(lat,lon,apikey,**kwargs):
- '''get current conditions in specified location, e.g.,
- lat = 42.2775 N, lon = 71.3468 W is Natick, MA, US
- get_current_weather('42.2775','-71.3468',key,units='metric')'''
-
- # Initialize json_data
- json_data = {'Feedback': 'nothing'}
-
- # Set a default of imperial units
- info = {'units':'imperial'}
- for key, value in kwargs.items():
- info[key] = value
-
- try:
- url = BASE_URL.format(lat,lon,info['units'],apikey)
- json_data = json.loads(urllib.request.urlopen(url).read())
- except urllib.error.URLError:
- # if the One Call weather API doesn't work, return an error
- print('We cannot access the weather service')
-
- return json_data
-
-
-def parse_current_json(json_data):
- '''parse and extract json data from the current weather data'''
- # Initialize weather_info
- weather_info = {'Feedback': 'nothing'}
-
- try:
- # select data of interest from dictionary
- weather_info = json_data["current"]
- # add current date and time
- weather_info['current_time'] = str(datetime.datetime.now())
- # make sure values are returned as floats
- weather_info['temp'] = float(weather_info['temp'])
- weather_info['feels_like'] = float(weather_info['feels_like'])
- weather_info['pressure'] = float(weather_info['pressure'])
- weather_info['humidity'] = float(weather_info['humidity'])
- weather_info['wind_speed'] = float(weather_info['wind_speed'])
- weather_info['wind_deg'] = float(weather_info['wind_deg'])
- weather_info['uvi'] = float(weather_info['uvi'])
- weather_info['clouds'] = float(weather_info['clouds'])
- weather_info['timezone'] = json_data['timezone']
-
- except KeyError as e:
- print('Something went wrong while parsing current json')
- raise e
-
- return weather_info
-
-
-def parse_forecast(json_data):
- '''parse and extract json data from the forecast weather data'''
-
- import array
-
- weather_info = {'Feedback': 'nothing'}
-
- try:
- timezone = json_data['timezone']
- data = json_data['hourly']
- # create arrays
- temp = []
- pressure = []
- humidity = []
- speed = []
- deg = []
- date = []
-
- # loop over all and add to arrays
- for i in range(48):
- x1 = data[i]
- temp.append(x1['temp'])
- pressure.append(x1['pressure'])
- humidity.append(x1['humidity'])
- speed.append(x1['wind_speed'])
- deg.append(x1['wind_deg'])
- date.append(x1['dt'])
-
- # create dictionary
- weather_info = dict(current_time=date,temp=temp,deg=deg,
- speed=speed,humidity=humidity,pressure=pressure,timezone=timezone)
- except KeyError as e:
- print('Something went wrong with parsing the forecast json.')
- raise e
-
- return weather_info
diff --git a/SoftwareTests/CheckTestResults.m b/SoftwareTests/CheckTestResults.m
index fef0728..579ad43 100644
--- a/SoftwareTests/CheckTestResults.m
+++ b/SoftwareTests/CheckTestResults.m
@@ -4,7 +4,7 @@
end
properties (ClassSetupParameter)
- Project = {''};
+ Project = {currentProject()};
end
properties (TestParameter)
@@ -15,8 +15,8 @@
methods (TestParameterDefinition,Static)
function Version = GetResults(Project)
- RootFolder = currentProject().RootFolder;
- Version = dir(fullfile(RootFolder,"SoftwareTests","TestResults*.txt"));
+ RootFolder = Project.RootFolder;
+ Version = dir(fullfile(RootFolder,"public","TestResults*.txt"));
Version = extractBetween([Version.name],"TestResults_",".txt");
end
@@ -37,9 +37,11 @@ function SetUpSmokeTest(testCase,Project)
methods(Test)
function CheckResults(testCase,Version)
- File = fullfile("SoftwareTests","TestResults_"+Version+".txt");
+ File = fullfile("public","TestResults_"+Version+".txt");
Results = readtable(File,TextType="string");
- testCase.verifyTrue(all(Results.Passed));
+ if ~all(Results.Passed)
+ error("Some of the tests did not pass.")
+ end
end
end
diff --git a/SoftwareTests/FunctionTests.m b/SoftwareTests/FunctionTests.m
index cfcd234..c490eb2 100644
--- a/SoftwareTests/FunctionTests.m
+++ b/SoftwareTests/FunctionTests.m
@@ -1,7 +1,14 @@
classdef FunctionTests < matlab.unittest.TestCase
+ % https://www.mathworks.com/help/matlab/matlab_prog/use-parameters-in-class-based-tests.html
+
methods(Test)
+ function IsKnownPythonVersion(testCase)
+ Known = CheckPythonVersion;
+ verifyTrue(testCase,Known)
+ end
+
end % methods
end % classdef
\ No newline at end of file
diff --git a/SoftwareTests/OrigSmokeTests.m b/SoftwareTests/OrigSmokeTests.m
new file mode 100644
index 0000000..e9a1427
--- /dev/null
+++ b/SoftwareTests/OrigSmokeTests.m
@@ -0,0 +1,149 @@
+classdef SmokeTests < matlab.unittest.TestCase
+
+ properties (ClassSetupParameter)
+ Project = {''};
+ end
+
+ properties (TestParameter)
+ Scripts;
+ end
+
+ methods (TestParameterDefinition,Static)
+
+ function Scripts = GetScriptName(Project)
+ RootFolder = currentProject().RootFolder;
+ Scripts = dir(fullfile(RootFolder,"Scripts","*.mlx"));
+ Scripts = {Scripts.name};
+ end
+
+ end
+
+ methods (TestClassSetup)
+
+ function SetUpSmokeTest(testCase,Project)
+ try
+ currentProject;
+ catch ME
+ warning("Project is not loaded.")
+ end
+ end
+
+
+ end
+
+
+
+ methods(Test)
+
+ function SmokeRun(testCase,Scripts)
+ Filename = string(Scripts);
+ switch (Filename)
+ case "CreateCurrentWeatherApp.mlx"
+ disp("Skipping " + Filename)
+ case "CheckingTheWeather.mlx"
+ txt = readlines("Response.json");
+ pycode = ["import checkcurrentweather"
+ "import json"
+ ""
+ "json_data = json.loads(txt)"
+ "currentWeather = checkcurrentweather.parse_current_json(json_data)"
+ ];
+ APISmokeTest(testCase,Filename,pycode,txt)
+ case "WeatherForecast.mlx"
+ % txt = readlines("ResponseOneCall.json");
+ % pycode = ["import checkweather"
+ % ""
+ % "json_data = json.loads(txt)"
+ % "currentWeather = checkweather.parse_current_json(json_data)"
+ % "forecastWeather = checkweather.parse_forecast_json(json_data)"
+ % ];
+ % APISmokeTest(testCase,Filename,pycode,txt)
+ case "SampleWeatherDashboard.mlx"
+
+ otherwise
+ SimpleSmokeTest(testCase,Filename)
+ end
+ end
+
+ end
+
+
+ methods (Access = private)
+
+ function APISmokeTest(testCase,Filename,pycode,txt)
+ RootFolder = currentProject().RootFolder;
+ cd(RootFolder)
+ cd Scripts
+ if Filename == "CheckingTheWeather.mlx"
+ [currentWeather] = pyrun(pycode, "currentWeather","txt",txt);
+ elseif Filename == "WeatherForecast.mlx"
+ [currentWeather,forecastWeather] = pyrun(pycode,["currentWeather","forecastWeather"],"txt",txt);
+ end
+
+ disp(">> Running " + Filename);
+ try
+ run(fullfile(Filename));
+ catch ME
+ testCase.verifyTrue(false,ME.message);
+ end
+
+ try
+ % Log the opened figures to the test reports
+ Figures = findall(groot,'Type','figure');
+ Figures = flipud(Figures);
+ if ~isempty(Figures)
+ for f = 1:size(Figures,1)
+ FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f));
+ log(testCase,1,FigDiag);
+ end
+ end
+ catch ME
+ disp("Failed to capture images")
+ end
+ close all
+ end
+
+ function RunMyFile(~,Filename)
+ run(Filename);
+ end
+
+ function SimpleSmokeTest(testCase,Filename)
+
+ % Run the Smoke test
+ RootFolder = currentProject().RootFolder;
+ cd(RootFolder)
+ disp(">> Running " + Filename);
+ try
+ RunMyFile(testCase,Filename)
+ catch ME
+ testCase.verifyTrue(false,ME.message);
+ end
+
+ % Log the opened figures to the test reports
+ try
+ Figures = findall(groot,'Type','figure');
+ Figures = flipud(Figures);
+ if ~isempty(Figures)
+ for f = 1:size(Figures,1)
+ FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f));
+ log(testCase,1,FigDiag);
+ end
+ end
+ catch ME
+ disp("Failed to capture figures")
+ end
+ close all
+
+ end
+
+ end
+
+ methods (TestClassTeardown)
+
+ function closeAllFigure(testCase)
+ close all force % Close figure windows
+ end
+
+ end % methods (TestClassTeardown)
+
+end
\ No newline at end of file
diff --git a/SoftwareTests/PostFiles/PostCheckingTheWeather.m b/SoftwareTests/PostFiles/PostCheckingTheWeather.m
new file mode 100644
index 0000000..5e1183b
--- /dev/null
+++ b/SoftwareTests/PostFiles/PostCheckingTheWeather.m
@@ -0,0 +1,3 @@
+% Post-run script for CheckingTheWeather.mlx
+% ---- Post-run commands -----
+
diff --git a/SoftwareTests/PostFiles/PostCheckingTheWeatherSoln.m b/SoftwareTests/PostFiles/PostCheckingTheWeatherSoln.m
new file mode 100644
index 0000000..3bca581
--- /dev/null
+++ b/SoftwareTests/PostFiles/PostCheckingTheWeatherSoln.m
@@ -0,0 +1,7 @@
+% Post-run script for CheckingTheWeatherSoln.mlx
+% ---- Post-run commands -----
+
+writelines("",fullfile(currentProject().RootFolder,"Scripts","myAPIkey.txt"))
+if exist(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","Response.json"),"file")
+ delete(fullfile(currentProject().RootFolder,"InstructorResources","Solutions","Response.json"))
+end
\ No newline at end of file
diff --git a/SoftwareTests/PostFiles/PostCreateCurrentWeatherApp.m b/SoftwareTests/PostFiles/PostCreateCurrentWeatherApp.m
new file mode 100644
index 0000000..9530d14
--- /dev/null
+++ b/SoftwareTests/PostFiles/PostCreateCurrentWeatherApp.m
@@ -0,0 +1,3 @@
+% Post-run script for CreateCurrentWeatherApp.mlx
+% ---- Post-run commands -----
+
diff --git a/SoftwareTests/PostFiles/PostCreateCurrentWeatherAppSoln.m b/SoftwareTests/PostFiles/PostCreateCurrentWeatherAppSoln.m
new file mode 100644
index 0000000..197fb02
--- /dev/null
+++ b/SoftwareTests/PostFiles/PostCreateCurrentWeatherAppSoln.m
@@ -0,0 +1,4 @@
+% Post-run script for CreateCurrentWeatherAppSoln.mlx
+% ---- Post-run commands -----
+
+delete(findall(groot,'Name','MATLAB App'))
\ No newline at end of file
diff --git a/SoftwareTests/PostFiles/PostUsingMATLABwithPython.m b/SoftwareTests/PostFiles/PostUsingMATLABwithPython.m
new file mode 100644
index 0000000..9416232
--- /dev/null
+++ b/SoftwareTests/PostFiles/PostUsingMATLABwithPython.m
@@ -0,0 +1,3 @@
+% Post-run script for UsingMATLABwithPython.mlx
+% ---- Post-run commands -----
+
diff --git a/SoftwareTests/PostFiles/PostUsingMATLABwithPythonSoln.m b/SoftwareTests/PostFiles/PostUsingMATLABwithPythonSoln.m
new file mode 100644
index 0000000..e6e41ac
--- /dev/null
+++ b/SoftwareTests/PostFiles/PostUsingMATLABwithPythonSoln.m
@@ -0,0 +1,3 @@
+% Post-run script for UsingMATLABwithPythonSoln.mlx
+% ---- Post-run commands -----
+
diff --git a/SoftwareTests/PostSmokeTest.m b/SoftwareTests/PostSmokeTest.m
new file mode 100644
index 0000000..080cd0b
--- /dev/null
+++ b/SoftwareTests/PostSmokeTest.m
@@ -0,0 +1,66 @@
+function PostSmokeTest(ShowReport)
+arguments
+ ShowReport (1,1) logical = false;
+end
+
+import matlab.unittest.plugins.TestRunnerPlugin;
+
+% Create the runner:
+Runner = matlab.unittest.TestRunner.withTextOutput;
+
+% Create report folder:
+Folder = fullfile(currentProject().RootFolder,"public");
+if ~isfolder(Folder)
+ mkdir(Folder)
+end
+
+% Add HTML plugin:
+Plugin = matlab.unittest.plugins.TestReportPlugin.producingHTML(Folder,...
+ "IncludingPassingDiagnostics",true,...
+ "IncludingCommandWindowText",false,...
+ "LoggingLevel",matlab.automation.Verbosity(1));
+Runner.addPlugin(Plugin);
+
+
+% Create Test Suite
+Suite = testsuite("CheckTestResults");
+
+% Run the test suite
+Results = Runner.run(Suite);
+
+
+% Format the results in a table and save them
+Results = table(Results');
+Version = extractBetween(string(Results.Name),"Version=",")");
+Passed = logical(Results.Passed);
+
+% Add link to other report
+File = fileread(fullfile("public","index.html"));
+for iVer = 1:length(Version)
+ File = replace(File,"Version="+Version(iVer),...
+ sprintf('%s ',Version(iVer),"Version="+Version(iVer)));
+end
+writelines(File,fullfile("public","index.html"),"WriteMode","overwrite");
+
+% Format the JSON file
+Badge = struct;
+Badge.schemaVersion = 1;
+Badge.label = "Test Status";
+if all(Passed)
+ Badge.color = "success";
+ Badge.message = join("R"+Version," | ");
+elseif any(Passed)
+ Badge.color = "yellowgreen";
+ Badge.message = join("R"+Version(Passed)," | ");
+elseif all(~Passed)
+ Badge.color = "critical";
+ Badge.message = join("R"+Version," | ");
+end
+Badge = jsonencode(Badge);
+writelines(Badge,fullfile("Images","TestedWith.json"));
+
+if ShowReport
+ web(fullfile(Folder,"index.html"))
+end
+
+end
\ No newline at end of file
diff --git a/SoftwareTests/PreFiles/PreCheckingTheWeather.m b/SoftwareTests/PreFiles/PreCheckingTheWeather.m
new file mode 100644
index 0000000..13788f4
--- /dev/null
+++ b/SoftwareTests/PreFiles/PreCheckingTheWeather.m
@@ -0,0 +1,17 @@
+% Pre-run script for CheckingTheWeather.mlx
+% ---- Known Issues -----
+KnownIssuesID = "";
+% ---- Pre-run commands -----
+
+txt = readlines("Response.json");
+curpath = pwd;
+mypath = fullfile(currentProject().RootFolder,"Scripts");
+cd(mypath)
+pycode = ["import checkcurrentweather"
+ "import json"
+ ""
+ "json_data = json.loads(txt)"
+ "currentWeather = checkcurrentweather.parse_current_json(json_data)"
+ ];
+[currentWeather] = pyrun(pycode, "currentWeather","txt",txt);
+cd(curpath)
\ No newline at end of file
diff --git a/SoftwareTests/PreFiles/PreCheckingTheWeatherSoln.m b/SoftwareTests/PreFiles/PreCheckingTheWeatherSoln.m
new file mode 100644
index 0000000..fdff0a6
--- /dev/null
+++ b/SoftwareTests/PreFiles/PreCheckingTheWeatherSoln.m
@@ -0,0 +1,23 @@
+% Pre-run script for CheckingTheWeatherSoln.mlx
+% ---- Known Issues -----
+KnownIssuesID = "";
+% ---- Pre-run commands -----
+
+try
+copyfile(fullfile(currentProject().RootFolder,"InternalFiles","Solutions","myAPIkey.txt"),...
+ fullfile(currentProject().RootFolder,"Scripts","myAPIkey.txt"))
+catch
+ copyfile("Response.json",fullfile(currentProject().RootFolder,"InstructorResources","Solutions","Response.json"))
+ pycode = ["import checkcurrentweather"
+ "import json"
+ ""
+ "json_data = json.load(open(""Response.json""))"
+ "currentWeather = checkcurrentweather.parse_current_json(json_data)"
+ ];
+ apikey = "TestString";
+ pyrun = @(txt,out,varargin)TestPyRun(pycode,out,varargin);
+end
+
+function out = TestPyRun(txt,in,varargin)
+out = pyrun(txt,in);
+end
diff --git a/SoftwareTests/PreFiles/PreCreateCurrentWeatherApp.m b/SoftwareTests/PreFiles/PreCreateCurrentWeatherApp.m
new file mode 100644
index 0000000..ca7aa9b
--- /dev/null
+++ b/SoftwareTests/PreFiles/PreCreateCurrentWeatherApp.m
@@ -0,0 +1,6 @@
+% Pre-run script for CreateCurrentWeatherApp.mlx
+% ---- Known Issues -----
+KnownIssuesID = "";
+% ---- Pre-run commands -----
+
+appdesigner = @()disp("Open App Designer here.");
\ No newline at end of file
diff --git a/SoftwareTests/PreFiles/PreCreateCurrentWeatherAppSoln.m b/SoftwareTests/PreFiles/PreCreateCurrentWeatherAppSoln.m
new file mode 100644
index 0000000..ece9e8e
--- /dev/null
+++ b/SoftwareTests/PreFiles/PreCreateCurrentWeatherAppSoln.m
@@ -0,0 +1,7 @@
+% Pre-run script for CreateCurrentWeatherAppSoln.mlx
+% ---- Known Issues -----
+KnownIssuesID = "";
+% ---- Pre-run commands -----
+
+open = @(x)run(x);
+
diff --git a/SoftwareTests/PreFiles/PreUsingMATLABwithPython.m b/SoftwareTests/PreFiles/PreUsingMATLABwithPython.m
new file mode 100644
index 0000000..7a4b22b
--- /dev/null
+++ b/SoftwareTests/PreFiles/PreUsingMATLABwithPython.m
@@ -0,0 +1,5 @@
+% Pre-run script for UsingMATLABwithPython.mlx
+% ---- Known Issues -----
+KnownIssuesID = "";
+% ---- Pre-run commands -----
+
diff --git a/SoftwareTests/PreFiles/PreUsingMATLABwithPythonSoln.m b/SoftwareTests/PreFiles/PreUsingMATLABwithPythonSoln.m
new file mode 100644
index 0000000..d8e1896
--- /dev/null
+++ b/SoftwareTests/PreFiles/PreUsingMATLABwithPythonSoln.m
@@ -0,0 +1,5 @@
+% Pre-run script for UsingMATLABwithPythonSoln.mlx
+% ---- Known Issues -----
+KnownIssuesID = "";
+% ---- Pre-run commands -----
+
diff --git a/SoftwareTests/PreFiles/Response.json b/SoftwareTests/PreFiles/Response.json
new file mode 100644
index 0000000..d8135a4
--- /dev/null
+++ b/SoftwareTests/PreFiles/Response.json
@@ -0,0 +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}
\ No newline at end of file
diff --git a/SoftwareTests/PreFiles/ResponseOneCall.json b/SoftwareTests/PreFiles/ResponseOneCall.json
new file mode 100644
index 0000000..676ca0b
--- /dev/null
+++ b/SoftwareTests/PreFiles/ResponseOneCall.json
@@ -0,0 +1,114 @@
+{
+ "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": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/SoftwareTests/ResponseOneCallOneLine.json b/SoftwareTests/ResponseOneCallOneLine.json
new file mode 100644
index 0000000..63c5ef7
--- /dev/null
+++ b/SoftwareTests/ResponseOneCallOneLine.json
@@ -0,0 +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": [ ]}] }
\ No newline at end of file
diff --git a/SoftwareTests/RunAllTests.m b/SoftwareTests/RunAllTests.m
index 87675d1..046a893 100644
--- a/SoftwareTests/RunAllTests.m
+++ b/SoftwareTests/RunAllTests.m
@@ -1,42 +1,42 @@
-function RunAllTest(EnableReport,ReportFolder)
+function RunAllTests(ShowReport)
arguments
- EnableReport (1,1) logical = false;
- ReportFolder (1,1) string = "public";
+ ShowReport (1,1) logical = false;
end
import matlab.unittest.plugins.TestReportPlugin;
% Create a runner
Runner = matlab.unittest.TestRunner.withTextOutput;
-if EnableReport
- Folder = fullfile(currentProject().RootFolder,ReportFolder);
- if ~isfolder(Folder)
- mkdir(Folder)
- else
- rmdir(Folder,'s')
- mkdir(Folder)
- end
- Plugin = TestReportPlugin.producingHTML(Folder,...
- "IncludingPassingDiagnostics",true,...
- "IncludingCommandWindowText",true,...
- "LoggingLevel",matlab.automation.Verbosity(1));
- Runner.addPlugin(Plugin);
+Folder = fullfile(currentProject().RootFolder,"public",version("-release"));
+if ~isfolder(Folder)
+ mkdir(Folder)
+else
+ rmdir(Folder,'s')
+ mkdir(Folder)
end
+Plugin = TestReportPlugin.producingHTML(Folder,...
+ "IncludingPassingDiagnostics",true,...
+ "IncludingCommandWindowText",true,...
+ "LoggingLevel",matlab.automation.Verbosity(1));
+Runner.addPlugin(Plugin);
+
% Create the test suite with SmokeTest and Function test if they exist
Suite = testsuite("SmokeTests");
Suite = [Suite testsuite("FunctionTests")];
+Suite = [Suite testsuite("SolnSmokeTests")];
% Run the test suite
Results = Runner.run(Suite);
-if EnableReport
+if ShowReport
web(fullfile(Folder,"index.html"))
end
% Format the results in a table and save them
ResultsTable = table(Results')
-writetable(ResultsTable,fullfile("SoftwareTests","TestResults_R"+version("-release")+".txt"));
+writetable(ResultsTable,fullfile(currentProject().RootFolder,...
+ "public","TestResults_"+version("-release")+".txt"));
% Assert success of test
assertSuccess(Results);
diff --git a/SoftwareTests/SmokeTests.m b/SoftwareTests/SmokeTests.m
index e9a1427..dac5c42 100644
--- a/SoftwareTests/SmokeTests.m
+++ b/SoftwareTests/SmokeTests.m
@@ -1,149 +1,152 @@
classdef SmokeTests < matlab.unittest.TestCase
+ properties
+ RootFolder
+ sparedEditors % Files already open when the test starts
+ end % properties
+
properties (ClassSetupParameter)
- Project = {''};
- end
+ Project = {currentProject()};
+ end % ClassSetupParameter
properties (TestParameter)
- Scripts;
- end
+ File;
+ end % TestParameter
methods (TestParameterDefinition,Static)
- function Scripts = GetScriptName(Project)
+ function File = RetrieveFile(Project) %#ok
+ % Retrieve student template files:
RootFolder = currentProject().RootFolder;
- Scripts = dir(fullfile(RootFolder,"Scripts","*.mlx"));
- Scripts = {Scripts.name};
+ File = dir(fullfile(RootFolder,"Scripts","*.m"));
+ File = [File; dir(fullfile(RootFolder,"Scripts","*.mlx"))];
+ File = {File.name};
end
- end
+ end % Static TestParameterDefinition
methods (TestClassSetup)
- function SetUpSmokeTest(testCase,Project)
- try
- currentProject;
- catch ME
- warning("Project is not loaded.")
- end
- end
-
-
- end
-
+ function SetUpSmokeTest(testCase,Project) %#ok
+ % Navigate to project root folder:
+ testCase.RootFolder = Project.RootFolder;
+ cd(testCase.RootFolder)
+
+ % Close the StartUp app if still open:
+ delete(findall(groot,'Name','StartUp App'))
+ % Log MATLAB version:
+ testCase.log("Running in " + version)
+ end
- methods(Test)
+ end % TestClassSetup
- function SmokeRun(testCase,Scripts)
- Filename = string(Scripts);
- switch (Filename)
- case "CreateCurrentWeatherApp.mlx"
- disp("Skipping " + Filename)
- case "CheckingTheWeather.mlx"
- txt = readlines("Response.json");
- pycode = ["import checkcurrentweather"
- "import json"
- ""
- "json_data = json.loads(txt)"
- "currentWeather = checkcurrentweather.parse_current_json(json_data)"
- ];
- APISmokeTest(testCase,Filename,pycode,txt)
- case "WeatherForecast.mlx"
- % txt = readlines("ResponseOneCall.json");
- % pycode = ["import checkweather"
- % ""
- % "json_data = json.loads(txt)"
- % "currentWeather = checkweather.parse_current_json(json_data)"
- % "forecastWeather = checkweather.parse_forecast_json(json_data)"
- % ];
- % APISmokeTest(testCase,Filename,pycode,txt)
- case "SampleWeatherDashboard.mlx"
-
- otherwise
- SimpleSmokeTest(testCase,Filename)
+ methods(TestMethodSetup)
+ function recordEditorsToSpare(testCase)
+ testCase.sparedEditors = matlab.desktop.editor.getAll;
+ testCase.sparedEditors = {testCase.sparedEditors.Filename};
+ end
+ end % TestMethodSetup
+
+ methods(TestMethodTeardown)
+ function closeOpenedEditors_thenDeleteWorkingDir(testCase)
+ openEditors = matlab.desktop.editor.getAll;
+ for editor=openEditors(1:end)
+ if any(strcmp(editor.Filename, testCase.sparedEditors))
+ continue;
+ end
+ % if not on our list, close the file
+ editor.close();
end
end
+ end % TestMethodTeardown
- end
+ methods(Test)
+ function SmokeRun(testCase,File)
- methods (Access = private)
+ % Navigate to project root folder:
+ cd(testCase.RootFolder)
+ FileToRun = string(File);
- function APISmokeTest(testCase,Filename,pycode,txt)
- RootFolder = currentProject().RootFolder;
- cd(RootFolder)
- cd Scripts
- if Filename == "CheckingTheWeather.mlx"
- [currentWeather] = pyrun(pycode, "currentWeather","txt",txt);
- elseif Filename == "WeatherForecast.mlx"
- [currentWeather,forecastWeather] = pyrun(pycode,["currentWeather","forecastWeather"],"txt",txt);
- end
+ % Pre-test:
+ PreFiles = CheckPreFile(testCase,FileToRun);
+ run(PreFiles);
- disp(">> Running " + Filename);
+ % Run SmokeTest
+ disp(">> Running " + FileToRun);
try
- run(fullfile(Filename));
- catch ME
- testCase.verifyTrue(false,ME.message);
+ run(fullfile("Scripts",FileToRun));
+ catch ME
+
end
- try
- % Log the opened figures to the test reports
+ % Post-test:
+ PostFiles = CheckPostFile(testCase,FileToRun);
+ run(PostFiles)
+
+ % Log every figure created during run:
Figures = findall(groot,'Type','figure');
Figures = flipud(Figures);
if ~isempty(Figures)
for f = 1:size(Figures,1)
- FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f));
- log(testCase,1,FigDiag);
+ if ~isempty(Figures(f).Number)
+ FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png');
+ log(testCase,1,FigDiag);
+ end
end
end
- catch ME
- disp("Failed to capture images")
- end
- close all
- end
- function RunMyFile(~,Filename)
- run(Filename);
- end
-
- function SimpleSmokeTest(testCase,Filename)
-
- % Run the Smoke test
- RootFolder = currentProject().RootFolder;
- cd(RootFolder)
- disp(">> Running " + Filename);
- try
- RunMyFile(testCase,Filename)
- catch ME
- testCase.verifyTrue(false,ME.message);
+ % Close all figures and Simulink models
+ close all force
+ if any(matlab.addons.installedAddons().Name == "Simulink")
+ bdclose all
end
- % Log the opened figures to the test reports
- try
- Figures = findall(groot,'Type','figure');
- Figures = flipud(Figures);
- if ~isempty(Figures)
- for f = 1:size(Figures,1)
- FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f));
- log(testCase,1,FigDiag);
+ % Rethrow error if any
+ if exist("ME","var")
+ if ~any(strcmp(ME.identifier,KnownIssuesID))
+ rethrow(ME)
end
end
- catch ME
- disp("Failed to capture figures")
- end
- close all
end
+
+ end % Test Methods
- end
- methods (TestClassTeardown)
+ methods (Access = private)
- function closeAllFigure(testCase)
- close all force % Close figure windows
+ function Path = CheckPreFile(testCase,Filename)
+ PreFile = "Pre"+extractBefore(Filename,".m")+".m";
+ PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile);
+ if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles"))
+ mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles"))
+ end
+ if ~isfile(PreFilePath)
+ writelines("% Pre-run script for "+Filename,PreFilePath)
+ writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append');
+ writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append');
+ writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append');
+ writelines(" ",PreFilePath,'WriteMode','append');
+ end
+ Path = PreFilePath;
+ end
+
+ function Path = CheckPostFile(testCase,Filename)
+ PostFile = "Post"+extractBefore(Filename,".m")+".m";
+ PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile);
+ if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles"))
+ mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles"))
+ end
+ if ~isfile(PostFilePath)
+ writelines("% Post-run script for "+Filename,PostFilePath)
+ writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append');
+ writelines(" ",PostFilePath,'WriteMode','append');
+ end
+ Path = PostFilePath;
end
- end % methods (TestClassTeardown)
+ end % Private Methods
-end
\ No newline at end of file
+end % Smoketests
\ No newline at end of file
diff --git a/SoftwareTests/SolnSmokeTests.m b/SoftwareTests/SolnSmokeTests.m
new file mode 100644
index 0000000..7caeb21
--- /dev/null
+++ b/SoftwareTests/SolnSmokeTests.m
@@ -0,0 +1,177 @@
+classdef SolnSmokeTests < matlab.unittest.TestCase
+
+ properties
+ RootFolder
+ isSolnOnPath
+ sparedEditors % Track open files
+ end % properties
+
+ properties (ClassSetupParameter)
+ Project = {currentProject()};
+ end % ClassSetupParameter
+
+ methods(TestMethodSetup)
+ function recordEditorsToSpare(testCase)
+ testCase.sparedEditors = matlab.desktop.editor.getAll;
+ testCase.sparedEditors = {testCase.sparedEditors.Filename};
+ end
+ end % TestMethodSetup
+
+ methods(TestMethodTeardown)
+ function closeOpenedEditors_thenDeleteWorkingDir(testCase)
+ openEditors = matlab.desktop.editor.getAll;
+ for editor=openEditors(1:end)
+ if any(strcmp(editor.Filename, testCase.sparedEditors))
+ continue;
+ end
+ % if not on our list, close the file
+ editor.close();
+ end
+ end
+ end % TestMethodTeardown
+
+ properties (TestParameter)
+ File;
+ end % TestParameter
+
+ methods (TestParameterDefinition,Static)
+
+ function File = GetScriptName(Project)
+ % Retrieve student template files:
+ RootFolder = Project.RootFolder;
+ File = dir(fullfile(RootFolder,"Scripts","*.m"));
+ File = [File; dir(fullfile(RootFolder,"Scripts","*.mlx"))];
+ File = {File.name};
+ end
+
+ end % Static TestParameterDefinition
+
+ methods (TestClassSetup)
+
+ function SetUpPath(testCase,Project)
+ % Navigate to project root folder:
+ testCase.RootFolder = Project.RootFolder;
+ cd(testCase.RootFolder)
+
+ % Check that solutions are on path:
+ testCase.isSolnOnPath = isfolder("Solutions");
+ if testCase.isSolnOnPath == 0
+ addpath(genpath(fullfile(testCase.RootFolder,"InstructorResources","Solutions")))
+ end
+
+ % Close the StartUp app if still open:
+ delete(findall(groot,'Name','StartUp App'))
+
+ % Log MATLAB version:
+ testCase.log("Running in " + version)
+
+ end % function setUpPath
+
+ end % methods (TestClassSetup)
+
+ methods(Test)
+
+ % Check that solutions files exist for each of the student
+ % templates
+ function ExistSolns(testCase,File)
+ SolutionName = replace(string(File),".m","Soln.m");
+ assert(exist(SolutionName,"file"),"Missing solutions for "+File);
+ end
+
+
+ function SmokeRun(testCase,File)
+
+ % Navigate to project root folder:
+ cd(testCase.RootFolder)
+ FileToRun = replace(string(File),".m","Soln.m");
+
+ % Pre-test:
+ PreFiles = CheckPreFile(testCase,FileToRun);
+ run(PreFiles);
+
+ % Run SmokeTest
+ disp(">> Running " + FileToRun);
+ try
+ run(fullfile("InstructorResources","Solutions",FileToRun));
+ catch ME
+
+ end
+
+ % Post-test:
+ PostFiles = CheckPostFile(testCase,FileToRun);
+ run(PostFiles)
+
+ % Log every figure created during run:
+ Figures = findall(groot,'Type','figure');
+ Figures = flipud(Figures);
+ if ~isempty(Figures)
+ for f = 1:size(Figures,1)
+ if ~isempty(Figures(f).Number)
+ FigDiag = matlab.unittest.diagnostics.FigureDiagnostic(Figures(f),'Formats','png');
+ log(testCase,1,FigDiag);
+ end
+ end
+ end
+
+ % Close all figures and Simulink models
+ close all force
+ if any(matlab.addons.installedAddons().Name == "Simulink")
+ bdclose all
+ end
+
+ % Rethrow error if any
+ if exist("ME","var")
+ if ~any(strcmp(ME.identifier,KnownIssuesID))
+ rethrow(ME)
+ end
+ end
+
+ end
+
+ end % Test Methods
+
+ methods (Access = private)
+
+ function Path = CheckPreFile(testCase,Filename)
+ PreFile = "Pre"+extractBefore(Filename,".m")+".m";
+ PreFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PreFiles",PreFile);
+ if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles"))
+ mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PreFiles"))
+ end
+ if ~isfile(PreFilePath)
+ writelines("% Pre-run script for "+Filename,PreFilePath)
+ writelines("% ---- Known Issues -----",PreFilePath,'WriteMode','append');
+ writelines("KnownIssuesID = "+char(34)+char(34)+";",PreFilePath,'WriteMode','append');
+ writelines("% ---- Pre-run commands -----",PreFilePath,'WriteMode','append');
+ writelines(" ",PreFilePath,'WriteMode','append');
+ end
+ Path = PreFilePath;
+ end
+
+ function Path = CheckPostFile(testCase,Filename)
+ PostFile = "Post"+extractBefore(Filename,".m")+".m";
+ PostFilePath = fullfile(testCase.RootFolder,"SoftwareTests","PostFiles",PostFile);
+ if ~isfolder(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles"))
+ mkdir(fullfile(testCase.RootFolder,"SoftwareTests/PostFiles"))
+ end
+ if ~isfile(PostFilePath)
+ writelines("% Post-run script for "+Filename,PostFilePath)
+ writelines("% ---- Post-run commands -----",PostFilePath,'WriteMode','append');
+ writelines(" ",PostFilePath,'WriteMode','append');
+ end
+ Path = PostFilePath;
+ end
+
+ end % Private Access Methods
+
+ methods (TestClassTeardown)
+
+ function ResetPath(testCase)
+ if ~testCase.isSolnOnPath && exist("Solutions","dir")
+ rmpath(genpath(fullfile(currentProject().RootFolder,"InstructorResources","Solutions")))
+ end
+ end
+
+ end % TestClassTeardown
+
+end % SolnSmokeTests
diff --git a/SoftwareTests/TestResults_R2023a.txt b/SoftwareTests/TestResults_R2023a.txt
new file mode 100644
index 0000000..5c9f3b0
--- /dev/null
+++ b/SoftwareTests/TestResults_R2023a.txt
@@ -0,0 +1,6 @@
+Name,Passed,Failed,Incomplete,Duration,Details
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CheckingTheWeather.mlx),1,0,0,8.2960691,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CreateCurrentWeatherApp.mlx),1,0,0,0.0004901,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=SampleWeatherDashboard.mlx),1,0,0,0.0004588,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=UsingMATLABwithPython.mlx),1,0,0,2.2924885,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=WeatherForecast.mlx),1,0,0,0.3437829,
diff --git a/SoftwareTests/TestResults_R2024a.txt b/SoftwareTests/TestResults_R2024a.txt
new file mode 100644
index 0000000..73f4a8d
--- /dev/null
+++ b/SoftwareTests/TestResults_R2024a.txt
@@ -0,0 +1,6 @@
+Name,Passed,Failed,Incomplete,Duration,Details
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CheckingTheWeather.mlx),1,0,0,0.1316994,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=CreateCurrentWeatherApp.mlx),1,0,0,0.0003877,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=SampleWeatherDashboard.mlx),1,0,0,0.000197,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=UsingMATLABwithPython.mlx),1,0,0,0.3888675,
+SmokeTests[Project=0x0_char]/SmokeRun(Scripts=WeatherForecast.mlx),1,0,0,0.0044386,
diff --git a/Utilities/OldVersions/CheckingTheWeatherOld.mlx b/Utilities/OldVersions/CheckingTheWeatherOld.mlx
deleted file mode 100644
index 735122b..0000000
Binary files a/Utilities/OldVersions/CheckingTheWeatherOld.mlx and /dev/null differ
diff --git a/Utilities/OldVersions/UsingMATLABwithPythonOld.mlx b/Utilities/OldVersions/UsingMATLABwithPythonOld.mlx
deleted file mode 100644
index 22483ab..0000000
Binary files a/Utilities/OldVersions/UsingMATLABwithPythonOld.mlx and /dev/null differ
diff --git a/Utilities/ProjectShutdown.m b/Utilities/ProjectShutdown.m
index 20b6121..8c3c77c 100644
--- a/Utilities/ProjectShutdown.m
+++ b/Utilities/ProjectShutdown.m
@@ -1,62 +1,2 @@
-% function ProjectShutdown
-% % Reset module to original state that is expected when loading in a new
-% % MATLAB version.
-% proj = currentProject;
-%
-% MoveFilesAround("R2023b","MainMenu.mlx",proj,Flag="Close")
-% MoveFilesAround("R2023b","README.mlx",proj,Flag="Close")
-% % MoveFilesAround("R2024a","UsingMATLABwithPython.mlx",proj,Flag="Close")
-% % MoveFilesAround("R2024a","CheckingTheWeather.mlx",proj,Flag="Close")
-%
-% end
-%
-% function MoveFilesAround(ReleaseString,FileString,proj,opts)
-% arguments
-% ReleaseString (1,1) string {mustBeRelease}
-% FileString (1,1) string {mustLookLikeFile}
-% proj
-% opts.OldStr (1,1) string = "Old"
-% opts.NewStr (1,1) string = "New"
-% opts.Flag (1,1) string {mustBeMember(opts.Flag,["Open" "Close"])} = "Open"
-% end
-%
-% if ~contains(ReleaseString,"R")
-% ReleaseString = "R"+ReleaseString;
-% end
-% [FileLoc,FileName,FileExt] = fileparts(which(FileString));
-%
-% if isMATLABReleaseOlderThan(ReleaseString)
-% FileStringOld = FileName+opts.OldStr+FileExt;
-% FileStringNew = FileName+opts.NewStr+FileExt;
-% FileString = string(FileName)+FileExt;
-% try
-% if opts.Flag == "Open"
-% if exist(fullfile(proj.RootFolder,"Utilities","OldVersions",FileStringOld),"file")
-% movefile(fullfile(FileLoc,FileString), fullfile("Utilities","OldVersions",FileStringNew))
-% movefile(fullfile("Utilities","OldVersions",FileStringOld),fullfile(FileLoc,FileString))
-% end
-% else
-% if exist(fullfile(proj.RootFolder,"Utilities","OldVersions",FileStringNew),"file")
-% movefile(fullfile(FileLoc,FileString), fullfile("Utilities","OldVersions",FileStringOld))
-% movefile(fullfile("Utilities","OldVersions",FileStringNew),fullfile(FileLoc,FileString))
-% end
-% end
-% catch
-% disp("Failed to move " + FileString + ".")
-% end
-% end
-% end
-%
-% function mustBeRelease(str)
-% if ~contains(str,"R")
-% str = "R"+str;
-% end
-% pattern = "R"+digitsPattern(4)+("a"|"b");
-% assert(matches(str,pattern),"ReleaseString must be a valid MATLAB release.")
-% end
-%
-% function mustLookLikeFile(str)
-% [~,f,e] = fileparts(str);
-% assert(~isempty(f))
-% assert(e==".mlx"|e==".m"|e==".slx")
-% end
\ No newline at end of file
+% Close the StartUp app if still open:
+delete(findall(groot,'Name','StartUp App'))
\ No newline at end of file
diff --git a/Utilities/ProjectStartup.m b/Utilities/ProjectStartup.m
deleted file mode 100644
index 605a6b5..0000000
--- a/Utilities/ProjectStartup.m
+++ /dev/null
@@ -1,76 +0,0 @@
-function ProjectStartup
-% Set up check for version number
-proj = currentProject;
-
-% Address changes in the MATLAB language and capabilities
-MoveFilesAround("R2023b","MainMenu.mlx",proj)
-MoveFilesAround("R2023b","README.mlx",proj)
-MoveFilesAround("R2024a","UsingMATLABwithPython.mlx",proj)
-MoveFilesAround("R2024a","CheckingTheWeather.mlx",proj)
-
-% Offer navigation aids and feedback opportunities
-ProjectStartupApp
-end
-
-function MoveFilesAround(ReleaseString,FileString,proj,opts)
-arguments
- ReleaseString (1,1) string {mustBeRelease}
- FileString (1,1) string {mustLookLikeFile}
- proj
- opts.OldStr (1,1) string = "Old"
- opts.NewStr (1,1) string = "New"
- opts.Flag (1,1) string {mustBeMember(opts.Flag,["Open" "Close"])} = "Open"
-end
-
-if ~contains(ReleaseString,"R")
- ReleaseString = "R"+ReleaseString;
-end
-[FileLoc,FileName,FileExt] = fileparts(which(FileString));
-
-FileStringOld = FileName+opts.OldStr+FileExt;
-FileStringNew = FileName+opts.NewStr+FileExt;
-FileString = string(FileName)+FileExt;
-
-if isMATLABReleaseOlderThan(ReleaseString)
- try
- if opts.Flag == "Open"
- if exist(fullfile(proj.RootFolder,"Utilities","OldVersions",FileStringOld),"file")
- movefile(fullfile(FileLoc,FileString), fullfile("Utilities","OldVersions",FileStringNew))
- movefile(fullfile("Utilities","OldVersions",FileStringOld),fullfile(FileLoc,FileString))
- end
- % else
- % if exist(fullfile(proj.RootFolder,"Utilities","OldVersions",FileStringNew),"file")
- % movefile(fullfile(FileLoc,FileString), fullfile("Utilities","OldVersions",FileStringOld))
- % movefile(fullfile("Utilities","OldVersions",FileStringNew),fullfile(FileLoc,FileString))
- % end
- end
- catch
- disp("Failed to move " + FileString + ".")
- end
-else
- try
- if opts.Flag == "Open"
- if exist(fullfile(proj.RootFolder,"Utilities","OldVersions",FileStringNew),"file")
- movefile(fullfile(FileLoc,FileString), fullfile("Utilities","OldVersions",FileStringOld))
- movefile(fullfile("Utilities","OldVersions",FileStringNew),fullfile(FileLoc,FileString))
- end
- end
- catch
- disp("Failed to move " + FileString + ".")
- end
-end
-end
-
-function mustBeRelease(str)
-if ~contains(str,"R")
- str = "R"+str;
-end
-pattern = "R"+digitsPattern(4)+("a"|"b");
-assert(matches(str,pattern),"ReleaseString must be a valid MATLAB release.")
-end
-
-function mustLookLikeFile(str)
-[~,f,e] = fileparts(str);
-assert(~isempty(f))
-assert(e==".mlx"|e==".m"|e==".slx")
-end
\ No newline at end of file
diff --git a/Utilities/ProjectStartupApp.m b/Utilities/ProjectStartupApp.m
index bd94512..0cb0ebb 100644
--- a/Utilities/ProjectStartupApp.m
+++ b/Utilities/ProjectStartupApp.m
@@ -2,85 +2,37 @@
% Properties that correspond to app components
properties (Access = public)
- UIFigure matlab.ui.Figure
- TabGroup matlab.ui.container.TabGroup
- WelcomeTab matlab.ui.container.Tab
- Image matlab.ui.control.Image
- READMEButton matlab.ui.control.Button
- ReviewUsButton matlab.ui.control.Button
- MainMenuButton matlab.ui.control.Button
- WelcomeTitle matlab.ui.control.Label
- TabReview matlab.ui.container.Tab
- OtherButton matlab.ui.control.Button
- StudentButton matlab.ui.control.Button
- FacultyButton matlab.ui.control.Button
- Q1 matlab.ui.control.Label
- ReviewTitle matlab.ui.control.Label
- ReviewText matlab.ui.control.Label
+ StartUpAppUIFigure matlab.ui.Figure
+ FeedBackPanel matlab.ui.container.Panel
+ FeedBackGrid matlab.ui.container.GridLayout
+ ReviewTitle matlab.ui.control.Label
+ ReviewText matlab.ui.control.Label
+ OtherButton matlab.ui.control.Button
+ StudentButton matlab.ui.control.Button
+ FacultyButton matlab.ui.control.Button
+ Q1 matlab.ui.control.Label
+ WelcomePanel matlab.ui.container.Panel
+ WelcomeGrid matlab.ui.container.GridLayout
+ WelcomeTitle matlab.ui.control.Label
+ CoverImage matlab.ui.control.Image
+ ReviewUsButton matlab.ui.control.Button
+ READMEButton matlab.ui.control.Button
+ MainMenuButton matlab.ui.control.Button
end
-
+ % Properties to be modified
properties (Access = private)
GitHubOrganization = "MathWorks-Teaching-Resources"; % Description
GitHubRepository = "Programming-A-Starter-Project-Using-MATLAB-and-Python";
+ ImagePath {mustBeFile} = fullfile("Images","windTokyo.gif");
end
-%% How to customize the app?
-%{
-
- This StartUp app is designed to be customized to your module. It
- requires a minimum number of customization:
-
- 1. Change "Module Template" in app.WelcomeTitle by your module name
- 2. Change "Module Template" in app.ReviewTitle by your module name
- 3. Change the GitHubRepository (line 25) to the correct value
- 4. Change image in app.Image by the cover image you would like for your
- module. This image should be located in rootFolder/Images
- 5. Create your MS Form:
- a. Make a copy of the Faculty and the Student Template surveys
- b. Customize the name of the survey to match the name of your
- survey
- c. Click on "Collect responses", select "Anyone can respond" and
- copy the form link to SetupAppLinks (see step 6).
- 5. Create your MS Sway:
- a. Go to MS Sway
- b. Create a blank sway
- c. Add the name of your module to the title box
- d. Click "Share", Select "Anyone with a link", Select "View"
- e. Copy the sway link to SetupAppLinks (see step 6).
- 6. Add the Survey and Sway link to Utilities/SurveyLinks using
- SetupAppLinks.mlx in InternalFiles/RequiredFunctions/StartUpFcn
- 7. Save > Export to .m file and save the result as
- Utilities/ProjectStartupApp.m
-
-%}
-
- methods (Access = private, Static)
- function pingSway(app)
- try
- if ~ispref("MCCTEAM")
- load Utilities\SurveyLinks.mat SwayLink
- webread(SwayLink);
- end
- catch
- end
- end
-
- function openStudentForm(app)
- try
- load Utilities\SurveyLinks.mat StudentFormLink
- web(StudentFormLink);
- catch
- end
- end
+ properties (Access = private)
+ InitPosition;
+ ProjectName;
+ end
- function openFacultyForm(app)
- try
- load Utilities\SurveyLinks.mat FacultyFormLink
- web(FacultyFormLink);
- catch
- end
- end
+ methods (Access = private, Static)
function saveSettings(isReviewed,numLoad)
try
@@ -98,8 +50,11 @@ function saveSettings(isReviewed,numLoad)
% Code that executes after component creation
function startupFcn(app)
- % Move gui to center of screen
- movegui(app.UIFigure,"center")
+ % Copy title and set cover image
+ app.ProjectName = currentProject().Name;
+ app.WelcomeTitle.Text = app.ProjectName;
+ app.ReviewTitle.Text = app.WelcomeTitle.Text;
+ app.CoverImage.ImageSource = app.ImagePath;
% Switch tab to review if has not been reviewed yet
if isfile(fullfile("Utilities","ProjectSettings.mat"))
@@ -110,36 +65,22 @@ function startupFcn(app)
numLoad = 1; % Initialize counter
end
- % Switch tab for review
+ % Select tab to display
if ~isReviewed && numLoad > 2
isReviewed = true;
- app.TabGroup.SelectedTab = app.TabReview;
+ app.FeedBackGrid.Parent = app.StartUpAppUIFigure;
+ else
+ app.WelcomeGrid.Parent = app.StartUpAppUIFigure;
end
+ app.InitPosition = app.StartUpAppUIFigure.Position;
% Save new settings
app.saveSettings(isReviewed,numLoad)
-
- % Download links to survey (should only work when module goes
- % public on GitHub)
- try
- import matlab.net.*
- import matlab.net.http.*
-
- Request = RequestMessage;
- Request.Method = 'GET';
- Address = URI("http://api.github.com/repos/"+app.GitHubOrganization+...
- "/"+app.GitHubRepository+"/contents/Utilities/SurveyLinks.mat");
- Request.Header = HeaderField("X-GitHub-Api-Version","2022-11-28");
- Request.Header(2) = HeaderField("Accept","application/vnd.github+json");
- [Answer,~,~] = send(Request,Address);
- websave(fullfile("Utilities/SurveyLinks.mat"),Answer.Body.Data.download_url);
- catch
- end
-
+
end
- % Close request function: UIFigure
- function UIFigureCloseRequest(app, event)
+ % Close request function: StartUpAppUIFigure
+ function StartUpAppUIFigureCloseRequest(app, event)
if event.Source == app.READMEButton
open README.mlx
elseif event.Source == app.MainMenuButton
@@ -158,38 +99,63 @@ function UIFigureCloseRequest(app, event)
% Button pushed function: MainMenuButton
function MainMenuButtonPushed(app, event)
- UIFigureCloseRequest(app,event)
+ StartUpAppUIFigureCloseRequest(app,event)
end
% Button pushed function: FacultyButton
function FacultyButtonPushed(app, event)
- app.pingSway;
- app.openFacultyForm;
- UIFigureCloseRequest(app,event)
+ % Open Faculty Form
+ import matlab.net.*
+ % Create the URI object with the base URL
+ uri = URI('https://forms.office.com/Pages/ResponsePage.aspx','literal');
+ % Set the Query property with an array of QueryParameter objects
+ uri.Query = [
+ QueryParameter('id', 'ETrdmUhDaESb3eUHKx3B5mlcO9AKxC5AgMAKBg6OKuBUNTVXVlBTS0lOU0hPRExYMldGWldVQUhIRC4u')
+ QueryParameter('r2017080ed20546d1a2db18fe36421929', app.ProjectName)
+ ];
+ web(strrep(uri.EncodedURI,"+","%20"))
+ StartUpAppUIFigureCloseRequest(app,event)
end
% Button pushed function: StudentButton
function StudentButtonPushed(app, event)
- app.pingSway;
- app.openStudentForm;
- UIFigureCloseRequest(app,event)
+ % Open Student Form
+ import matlab.net.*
+ % Create the URI object with the base URL
+ uri = URI('https://forms.office.com/Pages/ResponsePage.aspx','literal');
+ % Set the Query property with an array of QueryParameter objects
+ uri.Query = [
+ QueryParameter('id', 'ETrdmUhDaESb3eUHKx3B5mlcO9AKxC5AgMAKBg6OKuBUNlNBOVRZSDZHT1VTMzA4MjdHSUdVR0o3Vy4u')
+ QueryParameter('r362e367caa234debbf4f65a58a0338e6', app.ProjectName)
+ ];
+ web(strrep(uri.EncodedURI,"+","%20"))
+ StartUpAppUIFigureCloseRequest(app,event)
end
% Button pushed function: OtherButton
function OtherButtonPushed(app, event)
- app.pingSway;
- app.openStudentForm;
- UIFigureCloseRequest(app,event)
+ % Open Student Form
+ import matlab.net.*
+ % Create the URI object with the base URL
+ uri = URI('https://forms.office.com/Pages/ResponsePage.aspx','literal');
+ % Set the Query property with an array of QueryParameter objects
+ uri.Query = [
+ QueryParameter('id', 'ETrdmUhDaESb3eUHKx3B5mlcO9AKxC5AgMAKBg6OKuBUNlNBOVRZSDZHT1VTMzA4MjdHSUdVR0o3Vy4u')
+ QueryParameter('r362e367caa234debbf4f65a58a0338e6', app.ProjectName)
+ ];
+ web(strrep(uri.EncodedURI,"+","%20"))
+ StartUpAppUIFigureCloseRequest(app,event)
end
% Button pushed function: ReviewUsButton
function ReviewUsButtonPushed(app, event)
- app.TabGroup.SelectedTab = app.TabReview;
+ app.WelcomeGrid.Parent = app.WelcomePanel;
+ app.FeedBackGrid.Parent = app.StartUpAppUIFigure;
end
% Button pushed function: READMEButton
function READMEButtonPushed(app, event)
- UIFigureCloseRequest(app,event)
+ StartUpAppUIFigureCloseRequest(app,event)
end
end
@@ -199,134 +165,130 @@ function READMEButtonPushed(app, event)
% Create UIFigure and components
function createComponents(app)
- % Create UIFigure and hide until all components are created
- app.UIFigure = uifigure('Visible', 'off');
- app.UIFigure.AutoResizeChildren = 'off';
- app.UIFigure.Position = [100 100 276 430];
- app.UIFigure.Name = 'MATLAB App';
- app.UIFigure.Resize = 'off';
- app.UIFigure.CloseRequestFcn = createCallbackFcn(app, @UIFigureCloseRequest, true);
+ % Create StartUpAppUIFigure and hide until all components are created
+ app.StartUpAppUIFigure = uifigure('Visible', 'off');
+ app.StartUpAppUIFigure.AutoResizeChildren = 'off';
+ app.StartUpAppUIFigure.Position = [100 100 276 430];
+ app.StartUpAppUIFigure.Name = 'StartUp App';
+ app.StartUpAppUIFigure.CloseRequestFcn = createCallbackFcn(app, @StartUpAppUIFigureCloseRequest, true);
- % Create TabGroup
- app.TabGroup = uitabgroup(app.UIFigure);
- app.TabGroup.AutoResizeChildren = 'off';
- app.TabGroup.Position = [1 1 276 460];
+ % Create WelcomePanel
+ app.WelcomePanel = uipanel(app.StartUpAppUIFigure);
+ app.WelcomePanel.AutoResizeChildren = 'off';
+ app.WelcomePanel.Position = [-551 33 244 410];
- % Create WelcomeTab
- app.WelcomeTab = uitab(app.TabGroup);
- app.WelcomeTab.AutoResizeChildren = 'off';
- app.WelcomeTab.Title = 'Tab';
-
- % Create WelcomeTitle
- app.WelcomeTitle = uilabel(app.WelcomeTab);
- app.WelcomeTitle.HorizontalAlignment = 'center';
- app.WelcomeTitle.VerticalAlignment = 'top';
- app.WelcomeTitle.WordWrap = 'on';
- app.WelcomeTitle.FontSize = 20;
- app.WelcomeTitle.FontWeight = 'bold';
- app.WelcomeTitle.FontColor = [0.14 0.14 0.14];
- app.WelcomeTitle.Position = [30 345 219 74];
- app.WelcomeTitle.Text = ' Programming: A Starter Project Using MATLAB with Python';
+ % Create WelcomeGrid
+ app.WelcomeGrid = uigridlayout(app.WelcomePanel);
+ app.WelcomeGrid.ColumnWidth = {'1x', '8x', '1x'};
+ app.WelcomeGrid.RowHeight = {'2x', '5x', '1x', '1x', '1x'};
% Create MainMenuButton
- app.MainMenuButton = uibutton(app.WelcomeTab, 'push');
+ app.MainMenuButton = uibutton(app.WelcomeGrid, 'push');
app.MainMenuButton.ButtonPushedFcn = createCallbackFcn(app, @MainMenuButtonPushed, true);
- app.MainMenuButton.BackgroundColor = [0.129411764705882 0.129411764705882 0.129411764705882];
app.MainMenuButton.FontSize = 18;
- app.MainMenuButton.FontColor = [0.850980392156863 0.850980392156863 0.850980392156863];
- app.MainMenuButton.Position = [59 96 161 35];
+ app.MainMenuButton.Layout.Row = 3;
+ app.MainMenuButton.Layout.Column = 2;
app.MainMenuButton.Text = 'Main Menu';
- % Create ReviewUsButton
- app.ReviewUsButton = uibutton(app.WelcomeTab, 'push');
- app.ReviewUsButton.ButtonPushedFcn = createCallbackFcn(app, @ReviewUsButtonPushed, true);
- app.ReviewUsButton.BackgroundColor = [0.129411764705882 0.129411764705882 0.129411764705882];
- app.ReviewUsButton.FontSize = 18;
- app.ReviewUsButton.FontColor = [0.850980392156863 0.850980392156863 0.850980392156863];
- app.ReviewUsButton.Position = [59 10 161 35];
- app.ReviewUsButton.Text = 'Review Us';
-
% Create READMEButton
- app.READMEButton = uibutton(app.WelcomeTab, 'push');
+ app.READMEButton = uibutton(app.WelcomeGrid, 'push');
app.READMEButton.ButtonPushedFcn = createCallbackFcn(app, @READMEButtonPushed, true);
- app.READMEButton.BackgroundColor = [0.129411764705882 0.129411764705882 0.129411764705882];
app.READMEButton.FontSize = 18;
- app.READMEButton.FontColor = [0.850980392156863 0.850980392156863 0.850980392156863];
- app.READMEButton.Position = [59 53 161 35];
+ app.READMEButton.Layout.Row = 4;
+ app.READMEButton.Layout.Column = 2;
app.READMEButton.Text = 'README';
- % Create Image
- app.Image = uiimage(app.WelcomeTab);
- app.Image.Position = [16 141 245 209];
- app.Image.ImageSource = 'windTokyo.gif';
+ % Create ReviewUsButton
+ app.ReviewUsButton = uibutton(app.WelcomeGrid, 'push');
+ app.ReviewUsButton.ButtonPushedFcn = createCallbackFcn(app, @ReviewUsButtonPushed, true);
+ app.ReviewUsButton.FontSize = 18;
+ app.ReviewUsButton.Layout.Row = 5;
+ app.ReviewUsButton.Layout.Column = 2;
+ app.ReviewUsButton.Text = 'Review Us';
- % Create TabReview
- app.TabReview = uitab(app.TabGroup);
- app.TabReview.AutoResizeChildren = 'off';
- app.TabReview.Title = 'Tab2';
- app.TabReview.HandleVisibility = 'off';
+ % Create CoverImage
+ app.CoverImage = uiimage(app.WelcomeGrid);
+ app.CoverImage.Layout.Row = 2;
+ app.CoverImage.Layout.Column = [1 3];
+ app.CoverImage.ImageSource = 'windTokyo.gif';
- % Create ReviewText
- app.ReviewText = uilabel(app.TabReview);
- app.ReviewText.HorizontalAlignment = 'center';
- app.ReviewText.VerticalAlignment = 'top';
- app.ReviewText.WordWrap = 'on';
- app.ReviewText.FontSize = 18;
- app.ReviewText.FontColor = [0.14 0.14 0.14];
- app.ReviewText.Position = [16 243 245 69];
- app.ReviewText.Text = 'Plese help us improve your experience by answering a few questions.';
+ % Create WelcomeTitle
+ app.WelcomeTitle = uilabel(app.WelcomeGrid);
+ app.WelcomeTitle.HorizontalAlignment = 'center';
+ app.WelcomeTitle.VerticalAlignment = 'top';
+ app.WelcomeTitle.WordWrap = 'on';
+ app.WelcomeTitle.FontSize = 24;
+ app.WelcomeTitle.FontWeight = 'bold';
+ app.WelcomeTitle.Layout.Row = 1;
+ app.WelcomeTitle.Layout.Column = [1 3];
+ app.WelcomeTitle.Text = '';
- % Create ReviewTitle
- app.ReviewTitle = uilabel(app.TabReview);
- app.ReviewTitle.HorizontalAlignment = 'center';
- app.ReviewTitle.VerticalAlignment = 'top';
- app.ReviewTitle.WordWrap = 'on';
- app.ReviewTitle.FontSize = 20;
- app.ReviewTitle.FontWeight = 'bold';
- app.ReviewTitle.FontColor = [0.14 0.14 0.14];
- app.ReviewTitle.Position = [2 326 274 93];
- app.ReviewTitle.Text = ' Programming: A Starter Project Using MATLAB with Python';
+ % Create FeedBackPanel
+ app.FeedBackPanel = uipanel(app.StartUpAppUIFigure);
+ app.FeedBackPanel.AutoResizeChildren = 'off';
+ app.FeedBackPanel.Position = [-291 33 236 409];
+
+ % Create FeedBackGrid
+ app.FeedBackGrid = uigridlayout(app.FeedBackPanel);
+ app.FeedBackGrid.ColumnWidth = {'1x', '8x', '1x'};
+ app.FeedBackGrid.RowHeight = {'2x', '3x', '2x', '1x', '1x', '1x'};
% Create Q1
- app.Q1 = uilabel(app.TabReview);
+ app.Q1 = uilabel(app.FeedBackGrid);
app.Q1.HorizontalAlignment = 'center';
- app.Q1.VerticalAlignment = 'top';
app.Q1.WordWrap = 'on';
app.Q1.FontSize = 18;
app.Q1.FontWeight = 'bold';
- app.Q1.FontColor = [0.14 0.14 0.14];
- app.Q1.Position = [16 141 245 69];
- app.Q1.Text = 'What describe you best?';
+ app.Q1.Layout.Row = 3;
+ app.Q1.Layout.Column = [1 3];
+ app.Q1.Text = 'What describes you best?';
% Create FacultyButton
- app.FacultyButton = uibutton(app.TabReview, 'push');
+ app.FacultyButton = uibutton(app.FeedBackGrid, 'push');
app.FacultyButton.ButtonPushedFcn = createCallbackFcn(app, @FacultyButtonPushed, true);
- app.FacultyButton.BackgroundColor = [0.129411764705882 0.129411764705882 0.129411764705882];
app.FacultyButton.FontSize = 18;
- app.FacultyButton.FontColor = [0.850980392156863 0.850980392156863 0.850980392156863];
- app.FacultyButton.Position = [64 127 150 40];
+ app.FacultyButton.Layout.Row = 4;
+ app.FacultyButton.Layout.Column = 2;
app.FacultyButton.Text = 'Faculty';
% Create StudentButton
- app.StudentButton = uibutton(app.TabReview, 'push');
+ app.StudentButton = uibutton(app.FeedBackGrid, 'push');
app.StudentButton.ButtonPushedFcn = createCallbackFcn(app, @StudentButtonPushed, true);
- app.StudentButton.BackgroundColor = [0.129411764705882 0.129411764705882 0.129411764705882];
app.StudentButton.FontSize = 18;
- app.StudentButton.FontColor = [0.850980392156863 0.850980392156863 0.850980392156863];
- app.StudentButton.Position = [64 80 150 40];
+ app.StudentButton.Layout.Row = 5;
+ app.StudentButton.Layout.Column = 2;
app.StudentButton.Text = 'Student';
% Create OtherButton
- app.OtherButton = uibutton(app.TabReview, 'push');
+ app.OtherButton = uibutton(app.FeedBackGrid, 'push');
app.OtherButton.ButtonPushedFcn = createCallbackFcn(app, @OtherButtonPushed, true);
- app.OtherButton.BackgroundColor = [0.129411764705882 0.129411764705882 0.129411764705882];
app.OtherButton.FontSize = 18;
- app.OtherButton.FontColor = [0.850980392156863 0.850980392156863 0.850980392156863];
- app.OtherButton.Position = [64 34 150 40];
+ app.OtherButton.Layout.Row = 6;
+ app.OtherButton.Layout.Column = 2;
app.OtherButton.Text = 'Other';
+ % Create ReviewText
+ app.ReviewText = uilabel(app.FeedBackGrid);
+ app.ReviewText.HorizontalAlignment = 'center';
+ app.ReviewText.WordWrap = 'on';
+ app.ReviewText.FontSize = 14;
+ app.ReviewText.Layout.Row = 2;
+ app.ReviewText.Layout.Column = [1 3];
+ app.ReviewText.Text = 'Please help us improve your experience by answering a few questions.';
+
+ % Create ReviewTitle
+ app.ReviewTitle = uilabel(app.FeedBackGrid);
+ app.ReviewTitle.HorizontalAlignment = 'center';
+ app.ReviewTitle.VerticalAlignment = 'top';
+ app.ReviewTitle.WordWrap = 'on';
+ app.ReviewTitle.FontSize = 24;
+ app.ReviewTitle.FontWeight = 'bold';
+ app.ReviewTitle.Layout.Row = 1;
+ app.ReviewTitle.Layout.Column = [1 3];
+ app.ReviewTitle.Text = '';
+
% Show the figure after all components are created
- app.UIFigure.Visible = 'on';
+ app.StartUpAppUIFigure.Visible = 'on';
end
end
@@ -340,7 +302,7 @@ function createComponents(app)
createComponents(app)
% Register the app with App Designer
- registerApp(app, app.UIFigure)
+ registerApp(app, app.StartUpAppUIFigure)
% Execute the startup function
runStartupFcn(app, @startupFcn)
@@ -354,7 +316,7 @@ function createComponents(app)
function delete(app)
% Delete UIFigure when app is deleted
- delete(app.UIFigure)
+ delete(app.StartUpAppUIFigure)
end
end
end
\ No newline at end of file
diff --git a/Utilities/SurveyLinks.mat b/Utilities/SurveyLinks.mat
deleted file mode 100644
index 0b1802a..0000000
Binary files a/Utilities/SurveyLinks.mat and /dev/null differ
diff --git a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/LTFuMOAnbbe8rFATn9tsEWBYh1Qd.xml b/resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/5R7G30JHZVF_lDxt6auPkBjLcVUd.xml
similarity index 72%
rename from resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/LTFuMOAnbbe8rFATn9tsEWBYh1Qd.xml
rename to resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/5R7G30JHZVF_lDxt6auPkBjLcVUd.xml
index 7a6326b..99772b4 100644
--- a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/LTFuMOAnbbe8rFATn9tsEWBYh1Qd.xml
+++ b/resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/5R7G30JHZVF_lDxt6auPkBjLcVUd.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/5R7G30JHZVF_lDxt6auPkBjLcVUp.xml b/resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/5R7G30JHZVF_lDxt6auPkBjLcVUp.xml
new file mode 100644
index 0000000..2ca006b
--- /dev/null
+++ b/resources/project/2zjcQkVJSJ_AwC9M8R9BTSESRzc/5R7G30JHZVF_lDxt6auPkBjLcVUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml b/resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml
new file mode 100644
index 0000000..ff2009c
--- /dev/null
+++ b/resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml b/resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml
new file mode 100644
index 0000000..3b8316b
--- /dev/null
+++ b/resources/project/6xhH2l9GP9loT6TdFn_Mo65sDHg/P8PSrqcBHMbGhqD2r1d9oc0h3TUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/CNywfkA_sVJKQVIu_dt3FgNM43gd.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/CNywfkA_sVJKQVIu_dt3FgNM43gd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/CNywfkA_sVJKQVIu_dt3FgNM43gd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/CNywfkA_sVJKQVIu_dt3FgNM43gp.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/CNywfkA_sVJKQVIu_dt3FgNM43gp.xml
new file mode 100644
index 0000000..c83abf5
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/CNywfkA_sVJKQVIu_dt3FgNM43gp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cNV9fbD7U86DbYesWtgxlSbObDsd.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cNV9fbD7U86DbYesWtgxlSbObDsd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cNV9fbD7U86DbYesWtgxlSbObDsd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cNV9fbD7U86DbYesWtgxlSbObDsp.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cNV9fbD7U86DbYesWtgxlSbObDsp.xml
new file mode 100644
index 0000000..1bc0750
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/cNV9fbD7U86DbYesWtgxlSbObDsp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/eKfjzGwp0oXUNjB8dt6OlGMU7rQd.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/eKfjzGwp0oXUNjB8dt6OlGMU7rQd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/eKfjzGwp0oXUNjB8dt6OlGMU7rQd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/eKfjzGwp0oXUNjB8dt6OlGMU7rQp.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/eKfjzGwp0oXUNjB8dt6OlGMU7rQp.xml
new file mode 100644
index 0000000..bbde243
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/eKfjzGwp0oXUNjB8dt6OlGMU7rQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h5s8ch2zj9r3lWUKcsOjX8zQlFsd.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h5s8ch2zj9r3lWUKcsOjX8zQlFsd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h5s8ch2zj9r3lWUKcsOjX8zQlFsd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h5s8ch2zj9r3lWUKcsOjX8zQlFsp.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h5s8ch2zj9r3lWUKcsOjX8zQlFsp.xml
new file mode 100644
index 0000000..0f2387d
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/h5s8ch2zj9r3lWUKcsOjX8zQlFsp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/hXn6UklILyp-D_dXtEVXkR6HWa0d.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/hXn6UklILyp-D_dXtEVXkR6HWa0d.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/hXn6UklILyp-D_dXtEVXkR6HWa0d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/hXn6UklILyp-D_dXtEVXkR6HWa0p.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/hXn6UklILyp-D_dXtEVXkR6HWa0p.xml
new file mode 100644
index 0000000..81d26d5
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/hXn6UklILyp-D_dXtEVXkR6HWa0p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/qu4wtrgMg5JS7iVtXmbBSA9GENId.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/qu4wtrgMg5JS7iVtXmbBSA9GENId.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/qu4wtrgMg5JS7iVtXmbBSA9GENId.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/qu4wtrgMg5JS7iVtXmbBSA9GENIp.xml b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/qu4wtrgMg5JS7iVtXmbBSA9GENIp.xml
new file mode 100644
index 0000000..b0bbaec
--- /dev/null
+++ b/resources/project/BT5hWoz-UTefONdqForZyI91O8Y/qu4wtrgMg5JS7iVtXmbBSA9GENIp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4d.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4d.xml
index 28c2dcb..6c2fd15 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4d.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4d.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4p.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4p.xml
index 3bb1962..66245ed 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4p.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/-upqjogKesBp3DwJRlG6KjrKvd4p.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml
index 8028b69..ad72581 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8d.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml
index f400fff..d8cbcb9 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/2vfmNT5dFMoKB5FDZBSr3ouDAL8p.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml
index 017213c..8978875 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sd.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml
index 79b60d2..f842b96 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/DxJWFQ6s-5tgLo-3uCpCdq16n-sp.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8d.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8d.xml
new file mode 100644
index 0000000..f8d0933
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8p.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8p.xml
new file mode 100644
index 0000000..516dcb8
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/JzO7EW4RnUYzi9OV7qh3x-wX4z8p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0d.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0d.xml
deleted file mode 100644
index aee0cde..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0d.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0p.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0p.xml
deleted file mode 100644
index d1e8194..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/Pq7gqYnkFyhKab7XB8O0iwQTIP0p.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml
index b343995..c75735a 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgd.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml
index f4c79a2..a3b49bd 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/cn2Ee7NifKI7ffnw_Fjz5lrC1Qgp.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsd.xml
new file mode 100644
index 0000000..52eac4e
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsp.xml
new file mode 100644
index 0000000..c1f9f02
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/dzjyExK2OLpL1YhePZIjY4vjrpsp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gd.xml
index 3d666d2..db0a237 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gd.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gd.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gp.xml
index 924faaa..f329c5a 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gp.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/e7wCov_BYJUY6VsFZYx5ab3064gp.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUd.xml
index aee0cde..cdddfcf 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUd.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUd.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUp.xml
index 1dd7d6c..635b49b 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUp.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/ikoU0GqEAVreEIpyvUR8mCIaiqUp.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMd.xml
index 6ed1020..50dd813 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMd.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMd.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMp.xml
index f498f90..455e98b 100644
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMp.xml
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lMJoqU1GA86jWAvX6adHL2EbMzMp.xml
@@ -1,2 +1,2 @@
-
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4d.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4d.xml
deleted file mode 100644
index b343995..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4d.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4p.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4p.xml
deleted file mode 100644
index 21379fc..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/nBednXcpm1PUS8qxyRkFXdab-P4p.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/Yxkg-DfklTv8uiIAZptPJ3X2mowd.xml b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/Yxkg-DfklTv8uiIAZptPJ3X2mowd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/Yxkg-DfklTv8uiIAZptPJ3X2mowd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/Yxkg-DfklTv8uiIAZptPJ3X2mowp.xml b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/Yxkg-DfklTv8uiIAZptPJ3X2mowp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/Yxkg-DfklTv8uiIAZptPJ3X2mowp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/lUEE6oMS266pXRAZlg3smfxXDbgd.xml b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/lUEE6oMS266pXRAZlg3smfxXDbgd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/lUEE6oMS266pXRAZlg3smfxXDbgd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/lUEE6oMS266pXRAZlg3smfxXDbgp.xml b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/lUEE6oMS266pXRAZlg3smfxXDbgp.xml
new file mode 100644
index 0000000..4e217fb
--- /dev/null
+++ b/resources/project/GKJsEpq9HmT2JOvWOg3ZiDtMKEI/lUEE6oMS266pXRAZlg3smfxXDbgp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml b/resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml
index c647e63..4a6ad83 100644
--- a/resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml
+++ b/resources/project/HoHDHQ_WvHAAKj5aJOrvrg_vpt8/xXlmKuOQ7YT_G1elNhbKQIUqSRMd.xml
@@ -1,2 +1,2 @@
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/V76yfcu8kfyIeJKa13j7YbWR_NEd.xml b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/V76yfcu8kfyIeJKa13j7YbWR_NEd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/V76yfcu8kfyIeJKa13j7YbWR_NEd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/V76yfcu8kfyIeJKa13j7YbWR_NEp.xml b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/V76yfcu8kfyIeJKa13j7YbWR_NEp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/V76yfcu8kfyIeJKa13j7YbWR_NEp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/p2B2kuKn-TR4inf0L2-zoGElvj0d.xml b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/p2B2kuKn-TR4inf0L2-zoGElvj0d.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/p2B2kuKn-TR4inf0L2-zoGElvj0d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/p2B2kuKn-TR4inf0L2-zoGElvj0p.xml b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/p2B2kuKn-TR4inf0L2-zoGElvj0p.xml
new file mode 100644
index 0000000..db2f6df
--- /dev/null
+++ b/resources/project/I-dDyJ1p--Q0ihIJ8NFdLVLQLTU/p2B2kuKn-TR4inf0L2-zoGElvj0p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0d.xml b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0d.xml
new file mode 100644
index 0000000..31836f0
--- /dev/null
+++ b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0d.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0p.xml b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0p.xml
new file mode 100644
index 0000000..1986cbb
--- /dev/null
+++ b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/jYpi1Pu6k-AfWEJrahCTREe7wz0p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/uIYthjUuDNIiVXAl0s2ACeCA7XYd.xml b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/uIYthjUuDNIiVXAl0s2ACeCA7XYd.xml
deleted file mode 100644
index 57d8832..0000000
--- a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/uIYthjUuDNIiVXAl0s2ACeCA7XYd.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/uIYthjUuDNIiVXAl0s2ACeCA7XYp.xml b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/uIYthjUuDNIiVXAl0s2ACeCA7XYp.xml
deleted file mode 100644
index c132d44..0000000
--- a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/uIYthjUuDNIiVXAl0s2ACeCA7XYp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84d.xml b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84d.xml
index 50f7fa8..dc157b3 100644
--- a/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84d.xml
+++ b/resources/project/KAXfQgCar2Yb8zOxgvf9hdmLP1E/xcK8fO1pjra5DR0jot5vrzlBV84d.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Ud.xml b/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Ud.xml
deleted file mode 100644
index 609caf9..0000000
--- a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Ud.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Up.xml b/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Up.xml
deleted file mode 100644
index 5644fc9..0000000
--- a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Up.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEd.xml b/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEd.xml
deleted file mode 100644
index 609caf9..0000000
--- a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEd.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEp.xml b/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEp.xml
deleted file mode 100644
index 21c5916..0000000
--- a/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/423KLn4R-ovXBwba8WqQP1OUOKQd.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/423KLn4R-ovXBwba8WqQP1OUOKQd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/423KLn4R-ovXBwba8WqQP1OUOKQd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/423KLn4R-ovXBwba8WqQP1OUOKQp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/423KLn4R-ovXBwba8WqQP1OUOKQp.xml
new file mode 100644
index 0000000..de0d0b8
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/423KLn4R-ovXBwba8WqQP1OUOKQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/4P66G48h4uNHb9ng6NyN6i-qzUgd.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/4P66G48h4uNHb9ng6NyN6i-qzUgd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/4P66G48h4uNHb9ng6NyN6i-qzUgd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/4P66G48h4uNHb9ng6NyN6i-qzUgp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/4P66G48h4uNHb9ng6NyN6i-qzUgp.xml
new file mode 100644
index 0000000..433ac3a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/4P66G48h4uNHb9ng6NyN6i-qzUgp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/5geZ6FmFP1wNQNTkBPiRBgM6q-Ud.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/5geZ6FmFP1wNQNTkBPiRBgM6q-Ud.xml
new file mode 100644
index 0000000..378b613
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/5geZ6FmFP1wNQNTkBPiRBgM6q-Ud.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/5geZ6FmFP1wNQNTkBPiRBgM6q-Up.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/5geZ6FmFP1wNQNTkBPiRBgM6q-Up.xml
new file mode 100644
index 0000000..a990ac4
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/5geZ6FmFP1wNQNTkBPiRBgM6q-Up.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/MCVCPT9iaAzOGyx97P9tMdlmgCId.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/MCVCPT9iaAzOGyx97P9tMdlmgCId.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/MCVCPT9iaAzOGyx97P9tMdlmgCId.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/MCVCPT9iaAzOGyx97P9tMdlmgCIp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/MCVCPT9iaAzOGyx97P9tMdlmgCIp.xml
new file mode 100644
index 0000000..c79dd14
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/MCVCPT9iaAzOGyx97P9tMdlmgCIp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/OrFTDQK52Rk7nEyrvqtK57u0xLQd.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/OrFTDQK52Rk7nEyrvqtK57u0xLQd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/OrFTDQK52Rk7nEyrvqtK57u0xLQd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/OrFTDQK52Rk7nEyrvqtK57u0xLQp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/OrFTDQK52Rk7nEyrvqtK57u0xLQp.xml
new file mode 100644
index 0000000..f8892bd
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/OrFTDQK52Rk7nEyrvqtK57u0xLQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/r70to_aGHzGrK5Js1OM3qM-7FQId.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/WS0nNp0eS-otExzyipU1hnjde8Yd.xml
similarity index 72%
rename from resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/r70to_aGHzGrK5Js1OM3qM-7FQId.xml
rename to resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/WS0nNp0eS-otExzyipU1hnjde8Yd.xml
index 7a6326b..99772b4 100644
--- a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/r70to_aGHzGrK5Js1OM3qM-7FQId.xml
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/WS0nNp0eS-otExzyipU1hnjde8Yd.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/WS0nNp0eS-otExzyipU1hnjde8Yp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/WS0nNp0eS-otExzyipU1hnjde8Yp.xml
new file mode 100644
index 0000000..8873bdf
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/WS0nNp0eS-otExzyipU1hnjde8Yp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/b3JIy73ZrzFnWNgKhssf5hAuqQ4d.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/b3JIy73ZrzFnWNgKhssf5hAuqQ4d.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/b3JIy73ZrzFnWNgKhssf5hAuqQ4d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/b3JIy73ZrzFnWNgKhssf5hAuqQ4p.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/b3JIy73ZrzFnWNgKhssf5hAuqQ4p.xml
new file mode 100644
index 0000000..2e087b5
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/b3JIy73ZrzFnWNgKhssf5hAuqQ4p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gZEyOulxWBf_r9MGlsJJ-P82NOUd.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gZEyOulxWBf_r9MGlsJJ-P82NOUd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gZEyOulxWBf_r9MGlsJJ-P82NOUd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gZEyOulxWBf_r9MGlsJJ-P82NOUp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gZEyOulxWBf_r9MGlsJJ-P82NOUp.xml
new file mode 100644
index 0000000..fab485f
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gZEyOulxWBf_r9MGlsJJ-P82NOUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gfdF9UWoOuFoiyliJym7waW4XEkd.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gfdF9UWoOuFoiyliJym7waW4XEkd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gfdF9UWoOuFoiyliJym7waW4XEkd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gfdF9UWoOuFoiyliJym7waW4XEkp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gfdF9UWoOuFoiyliJym7waW4XEkp.xml
new file mode 100644
index 0000000..ab8d5f1
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/gfdF9UWoOuFoiyliJym7waW4XEkp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/tYqv97of56K959ec20E127ONNkkd.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/tYqv97of56K959ec20E127ONNkkd.xml
new file mode 100644
index 0000000..378b613
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/tYqv97of56K959ec20E127ONNkkd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/tYqv97of56K959ec20E127ONNkkp.xml b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/tYqv97of56K959ec20E127ONNkkp.xml
new file mode 100644
index 0000000..8031d61
--- /dev/null
+++ b/resources/project/ZN2RlSIbyWXhOxbxxI4hOawbMD4/tYqv97of56K959ec20E127ONNkkp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/LTFuMOAnbbe8rFATn9tsEWBYh1Qp.xml b/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/LTFuMOAnbbe8rFATn9tsEWBYh1Qp.xml
deleted file mode 100644
index 65c7868..0000000
--- a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/LTFuMOAnbbe8rFATn9tsEWBYh1Qp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/Y4iX7VSqYaXWuqu1GuH08Q4gCR4d.xml b/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/Y4iX7VSqYaXWuqu1GuH08Q4gCR4d.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/Y4iX7VSqYaXWuqu1GuH08Q4gCR4d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/Y4iX7VSqYaXWuqu1GuH08Q4gCR4p.xml b/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/Y4iX7VSqYaXWuqu1GuH08Q4gCR4p.xml
new file mode 100644
index 0000000..3dd7bef
--- /dev/null
+++ b/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/Y4iX7VSqYaXWuqu1GuH08Q4gCR4p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/r70to_aGHzGrK5Js1OM3qM-7FQIp.xml b/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/r70to_aGHzGrK5Js1OM3qM-7FQIp.xml
deleted file mode 100644
index f33e984..0000000
--- a/resources/project/ZdVxxv9BsNz7MGUxtEc6Pq3qh1M/r70to_aGHzGrK5Js1OM3qM-7FQIp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/nGmc4yUWSwVpS8w8tP7IolwQs0Ed.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/FclaQiuRRvqZzfnvReCKRLYQG04d.xml
similarity index 72%
rename from resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/nGmc4yUWSwVpS8w8tP7IolwQs0Ed.xml
rename to resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/FclaQiuRRvqZzfnvReCKRLYQG04d.xml
index 7a6326b..99772b4 100644
--- a/resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/nGmc4yUWSwVpS8w8tP7IolwQs0Ed.xml
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/FclaQiuRRvqZzfnvReCKRLYQG04d.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/FclaQiuRRvqZzfnvReCKRLYQG04p.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/FclaQiuRRvqZzfnvReCKRLYQG04p.xml
new file mode 100644
index 0000000..751b47c
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/FclaQiuRRvqZzfnvReCKRLYQG04p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/GJtrdTUc8krbVlhASJzieoFELdYd.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/GJtrdTUc8krbVlhASJzieoFELdYd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/GJtrdTUc8krbVlhASJzieoFELdYd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/GJtrdTUc8krbVlhASJzieoFELdYp.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/GJtrdTUc8krbVlhASJzieoFELdYp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/GJtrdTUc8krbVlhASJzieoFELdYp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/KQMigY2OjWa9g6M-C5r8Up0357od.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/KQMigY2OjWa9g6M-C5r8Up0357od.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/KQMigY2OjWa9g6M-C5r8Up0357od.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/KQMigY2OjWa9g6M-C5r8Up0357op.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/KQMigY2OjWa9g6M-C5r8Up0357op.xml
new file mode 100644
index 0000000..f6639b1
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/KQMigY2OjWa9g6M-C5r8Up0357op.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/ZL0yxdr5cvq5LeopyaxBqpitpjod.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/ZL0yxdr5cvq5LeopyaxBqpitpjod.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/ZL0yxdr5cvq5LeopyaxBqpitpjod.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/ZL0yxdr5cvq5LeopyaxBqpitpjop.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/ZL0yxdr5cvq5LeopyaxBqpitpjop.xml
new file mode 100644
index 0000000..433ac3a
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/ZL0yxdr5cvq5LeopyaxBqpitpjop.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/a2u5yuXrr23Y2L727aZhI7qT6L0d.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/a2u5yuXrr23Y2L727aZhI7qT6L0d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/a2u5yuXrr23Y2L727aZhI7qT6L0d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/a2u5yuXrr23Y2L727aZhI7qT6L0p.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/a2u5yuXrr23Y2L727aZhI7qT6L0p.xml
new file mode 100644
index 0000000..cded3de
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/a2u5yuXrr23Y2L727aZhI7qT6L0p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/cKSOiL8BaQ7iBaT8jcDLSFaxjZwd.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/cKSOiL8BaQ7iBaT8jcDLSFaxjZwd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/cKSOiL8BaQ7iBaT8jcDLSFaxjZwd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/cKSOiL8BaQ7iBaT8jcDLSFaxjZwp.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/cKSOiL8BaQ7iBaT8jcDLSFaxjZwp.xml
new file mode 100644
index 0000000..23ee4a6
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/cKSOiL8BaQ7iBaT8jcDLSFaxjZwp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/eYUVfav41Z3DHR_zeNxtEc1qeNQd.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/eYUVfav41Z3DHR_zeNxtEc1qeNQd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/eYUVfav41Z3DHR_zeNxtEc1qeNQd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/eYUVfav41Z3DHR_zeNxtEc1qeNQp.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/eYUVfav41Z3DHR_zeNxtEc1qeNQp.xml
new file mode 100644
index 0000000..72889d4
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/eYUVfav41Z3DHR_zeNxtEc1qeNQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/jeDtnYbvc6Yk7ncJK0puH-ERRmgd.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/jeDtnYbvc6Yk7ncJK0puH-ERRmgd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/jeDtnYbvc6Yk7ncJK0puH-ERRmgd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/jeDtnYbvc6Yk7ncJK0puH-ERRmgp.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/jeDtnYbvc6Yk7ncJK0puH-ERRmgp.xml
new file mode 100644
index 0000000..53eada2
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/jeDtnYbvc6Yk7ncJK0puH-ERRmgp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/taJ-MPP-S0lkh692qkaYjcSSzmsd.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/taJ-MPP-S0lkh692qkaYjcSSzmsd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/taJ-MPP-S0lkh692qkaYjcSSzmsd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/taJ-MPP-S0lkh692qkaYjcSSzmsp.xml b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/taJ-MPP-S0lkh692qkaYjcSSzmsp.xml
new file mode 100644
index 0000000..c79dd14
--- /dev/null
+++ b/resources/project/b3JIy73ZrzFnWNgKhssf5hAuqQ4/taJ-MPP-S0lkh692qkaYjcSSzmsp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/2w5jVWjTyrsOArdYS-TFzvwPxeQd.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/2w5jVWjTyrsOArdYS-TFzvwPxeQd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/2w5jVWjTyrsOArdYS-TFzvwPxeQd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/2w5jVWjTyrsOArdYS-TFzvwPxeQp.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/2w5jVWjTyrsOArdYS-TFzvwPxeQp.xml
new file mode 100644
index 0000000..5fd7791
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/2w5jVWjTyrsOArdYS-TFzvwPxeQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/TgS6JVkSWBMTwjsBx4_tl5SNRQsd.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/TgS6JVkSWBMTwjsBx4_tl5SNRQsd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/TgS6JVkSWBMTwjsBx4_tl5SNRQsd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/TgS6JVkSWBMTwjsBx4_tl5SNRQsp.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/TgS6JVkSWBMTwjsBx4_tl5SNRQsp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/TgS6JVkSWBMTwjsBx4_tl5SNRQsp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/W7HxaTKwnbY_JHKBUQsxSq-M7DId.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/W7HxaTKwnbY_JHKBUQsxSq-M7DId.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/W7HxaTKwnbY_JHKBUQsxSq-M7DId.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/W7HxaTKwnbY_JHKBUQsxSq-M7DIp.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/W7HxaTKwnbY_JHKBUQsxSq-M7DIp.xml
new file mode 100644
index 0000000..23b293a
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/W7HxaTKwnbY_JHKBUQsxSq-M7DIp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/eDyOl6rEuVOucYR_D6iogiukXU0d.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/eDyOl6rEuVOucYR_D6iogiukXU0d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/eDyOl6rEuVOucYR_D6iogiukXU0d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/eDyOl6rEuVOucYR_D6iogiukXU0p.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/eDyOl6rEuVOucYR_D6iogiukXU0p.xml
new file mode 100644
index 0000000..b5b34ac
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/eDyOl6rEuVOucYR_D6iogiukXU0p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/oBdTHGBwsy9mdLBLqTf4qrO3OgUd.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/oBdTHGBwsy9mdLBLqTf4qrO3OgUd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/oBdTHGBwsy9mdLBLqTf4qrO3OgUd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/oBdTHGBwsy9mdLBLqTf4qrO3OgUp.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/oBdTHGBwsy9mdLBLqTf4qrO3OgUp.xml
new file mode 100644
index 0000000..6260d4b
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/oBdTHGBwsy9mdLBLqTf4qrO3OgUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/q72DRlja6oz95_3ufhCRCr2JQ5Qd.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/q72DRlja6oz95_3ufhCRCr2JQ5Qd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/q72DRlja6oz95_3ufhCRCr2JQ5Qd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/q72DRlja6oz95_3ufhCRCr2JQ5Qp.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/q72DRlja6oz95_3ufhCRCr2JQ5Qp.xml
new file mode 100644
index 0000000..640c955
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/q72DRlja6oz95_3ufhCRCr2JQ5Qp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/u6SYVnPwrg97eiGyp5phLZfATsYd.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/u6SYVnPwrg97eiGyp5phLZfATsYd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/u6SYVnPwrg97eiGyp5phLZfATsYd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/u6SYVnPwrg97eiGyp5phLZfATsYp.xml b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/u6SYVnPwrg97eiGyp5phLZfATsYp.xml
new file mode 100644
index 0000000..3b09c20
--- /dev/null
+++ b/resources/project/gZEyOulxWBf_r9MGlsJJ-P82NOU/u6SYVnPwrg97eiGyp5phLZfATsYp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/nGmc4yUWSwVpS8w8tP7IolwQs0Ep.xml b/resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/nGmc4yUWSwVpS8w8tP7IolwQs0Ep.xml
deleted file mode 100644
index 371b133..0000000
--- a/resources/project/iMwdHOXOBiBXhnA_li8gtEJVTjc/nGmc4yUWSwVpS8w8tP7IolwQs0Ep.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/49hEt7xc-yV109-DLI01XSb5oAUd.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/49hEt7xc-yV109-DLI01XSb5oAUd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/49hEt7xc-yV109-DLI01XSb5oAUd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/49hEt7xc-yV109-DLI01XSb5oAUp.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/49hEt7xc-yV109-DLI01XSb5oAUp.xml
new file mode 100644
index 0000000..3eb6641
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/49hEt7xc-yV109-DLI01XSb5oAUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/71slgtYMdvtDd-aCg1j37m77sBQd.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/71slgtYMdvtDd-aCg1j37m77sBQd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/71slgtYMdvtDd-aCg1j37m77sBQd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/71slgtYMdvtDd-aCg1j37m77sBQp.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/71slgtYMdvtDd-aCg1j37m77sBQp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/71slgtYMdvtDd-aCg1j37m77sBQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/QBdt0OfZFDNvrKtB0lIq-wHjnf4d.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/QBdt0OfZFDNvrKtB0lIq-wHjnf4d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/QBdt0OfZFDNvrKtB0lIq-wHjnf4d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/QBdt0OfZFDNvrKtB0lIq-wHjnf4p.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/QBdt0OfZFDNvrKtB0lIq-wHjnf4p.xml
new file mode 100644
index 0000000..989e27c
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/QBdt0OfZFDNvrKtB0lIq-wHjnf4p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/bZkRvzxrhH4veiPi3nwMKeBp52gd.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/bZkRvzxrhH4veiPi3nwMKeBp52gd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/bZkRvzxrhH4veiPi3nwMKeBp52gd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/bZkRvzxrhH4veiPi3nwMKeBp52gp.xml b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/bZkRvzxrhH4veiPi3nwMKeBp52gp.xml
new file mode 100644
index 0000000..036032e
--- /dev/null
+++ b/resources/project/lUEE6oMS266pXRAZlg3smfxXDbg/bZkRvzxrhH4veiPi3nwMKeBp52gp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/0kK47cOHwsW7a1GaaqpQDigXMNUd.xml b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/0kK47cOHwsW7a1GaaqpQDigXMNUd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/0kK47cOHwsW7a1GaaqpQDigXMNUd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/0kK47cOHwsW7a1GaaqpQDigXMNUp.xml b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/0kK47cOHwsW7a1GaaqpQDigXMNUp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/0kK47cOHwsW7a1GaaqpQDigXMNUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/geuseqfzde5lmCB2PlA6wD238ucd.xml b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/geuseqfzde5lmCB2PlA6wD238ucd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/geuseqfzde5lmCB2PlA6wD238ucd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/geuseqfzde5lmCB2PlA6wD238ucp.xml b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/geuseqfzde5lmCB2PlA6wD238ucp.xml
new file mode 100644
index 0000000..9c44b89
--- /dev/null
+++ b/resources/project/p2B2kuKn-TR4inf0L2-zoGElvj0/geuseqfzde5lmCB2PlA6wD238ucp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/GKJsEpq9HmT2JOvWOg3ZiDtMKEId.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/GKJsEpq9HmT2JOvWOg3ZiDtMKEId.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/GKJsEpq9HmT2JOvWOg3ZiDtMKEId.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/GKJsEpq9HmT2JOvWOg3ZiDtMKEIp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/GKJsEpq9HmT2JOvWOg3ZiDtMKEIp.xml
new file mode 100644
index 0000000..6cd4da7
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/GKJsEpq9HmT2JOvWOg3ZiDtMKEIp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/I-dDyJ1p--Q0ihIJ8NFdLVLQLTUd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/I-dDyJ1p--Q0ihIJ8NFdLVLQLTUd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/I-dDyJ1p--Q0ihIJ8NFdLVLQLTUd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/I-dDyJ1p--Q0ihIJ8NFdLVLQLTUp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/I-dDyJ1p--Q0ihIJ8NFdLVLQLTUp.xml
new file mode 100644
index 0000000..a9c1803
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/I-dDyJ1p--Q0ihIJ8NFdLVLQLTUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAp.xml
new file mode 100644
index 0000000..77329db
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkp.xml
new file mode 100644
index 0000000..603491d
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/root/6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml b/resources/project/root/6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml
new file mode 100644
index 0000000..b1ca35e
--- /dev/null
+++ b/resources/project/root/6xhH2l9GP9loT6TdFn_Mo65sDHgp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml b/resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml
index f925747..438f9d5 100644
--- a/resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml
+++ b/resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml
@@ -1,2 +1,2 @@
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/resources/project/root/LUgSFhI3RPozNzNcutxrczVe6f0p.xml b/resources/project/root/LUgSFhI3RPozNzNcutxrczVe6f0p.xml
new file mode 100644
index 0000000..cfaf73d
--- /dev/null
+++ b/resources/project/root/LUgSFhI3RPozNzNcutxrczVe6f0p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file