├── .gitignore ├── README.md └── lessons ├── 00-our-engineering-problem ├── README.md ├── wall-in-context.png └── wall-reactions.svg ├── 01-variables-and-operations ├── README.md └── variables-and-operations.ipynb ├── 02-collections ├── README.md └── collections.ipynb ├── 03-loops ├── README.md └── loops.ipynb ├── 04-flow-control-and-if-statements ├── README.md └── flow-control-and-if-statements.ipynb ├── 05-functions ├── README.md └── functions.ipynb ├── 06-objects-and-properties ├── README.md └── objects.ipynb ├── 07-other-languages └── README.md ├── 08-environment-setup └── README.md ├── 09-json-basics-and-api ├── README.md └── api-diagram.png ├── 10-sending-json ├── README.md ├── manualCall.js ├── manualCall.py ├── skycivCall.js └── skycivCall.py ├── 11-receiving-json ├── README.md ├── index.js └── index.py ├── 12-skyciv-api-object └── README.md ├── 13-auth-and-options ├── README.md ├── index.js └── index.py ├── 14-s3d-model ├── README.md ├── index.js └── index.py ├── 15-functions ├── README.md ├── index.js └── index.py ├── 16-making-the-http-request ├── README.md ├── index.js └── index.py └── 17-interpreting-the-response ├── README.md ├── index.js ├── index.py ├── jsOutput.json └── pyOutput.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_store 3 | package.json 4 | package-lock.json 5 | pyOutput.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Welcome to the Offical SkyCiv Introduction to Programming Course 2 | 3 | In this course we will take you from no programming experience to using our world class Structural Analysis and Design API. 4 | 5 | ### How this course is different 6 | 7 | Too often programming courses use poor examples such as looping through an array of people's names and printing them to the console. As Structural Engineers, we understand this isn't ideal to help these new concepts sink in. 8 | 9 | Instead, we are going to take you from the very beginning using real life engineering examples. Want to see how an array, loops or if statements could be used in a Structural Engineering situation? We'll show you how. 10 | 11 | ### Course Content 12 | 13 | We've seperated each video lesson into a folder as seen in this repository. This will provide you with the code that you saw in each lesson for future reference. 14 | 15 | #### Section 1 16 |     0 (a). Introduction
17 |     0 (b). Our Engineering problem 18 | 1. Variables & Operations 19 | 2. Collections 20 | 3. Loops 21 | 4. Flow Control (If and Switch statements) 22 | 5. Functions 23 | 6. Objects and Properties 24 | 7. Other Languages 25 | 26 | #### Section 2 27 | 8. Setting up your Python and JavaScript Environment 28 | 9. What is an API and JSON basics 29 | 10. Sending JSON 30 | 11. Receiving JSON 31 | 32 | #### Section 3 33 | 12. The SkyCiv API Object 34 | 13. API Object - The auth and options properties 35 | 14. API Object - The SkyCiv s3d_model 36 | 15. API Object - The functions property 37 | 16. API Object - Sending the request 38 | 17. API Object - Interpreting the response -------------------------------------------------------------------------------- /lessons/00-our-engineering-problem/README.md: -------------------------------------------------------------------------------- 1 | # Our Engineering problem 2 | 3 | Throughout this course we will be learning our programming concepts in reference to a simple engineering problem that we want to solve. 4 | 5 | For this purpose, let's say we have a meshed wall in a 3D structural analysis model. Here is the meshed wall in _SkyCiv Structural 3D_: 6 | 7 | 8 | 9 | We can see that it comprises 12 elements and 20 nodes, 5 of which are supported. 10 | 11 | In _Structural 3D_ we can look at the reactions at these supports individually, but what if we wanted to know the total reaction at the base of the wall, in the center? 12 | 13 | For a single wall, it's easy - we just add up the reactions by hand, and that gives us the total force. We can also multiply each force, by its distance from where we want to calculate the moment, add those up, and that gives us the total moment. 14 | 15 | Now consider that we have a much larger model, with many more walls. What's wrong with this manual process? 16 | 17 | (i) Open to human error
18 | (ii) Repetitive and time consuming
19 | (iii) Boring
20 | (iv) Not really Engineering (just doing sums)
21 | 22 | >This might not be a calculation you personally need to do, but it's indicative of the _kind_ of repetitive calculations that you will no doubt be doing. 23 | 24 | ## Hello programming 25 | 26 | So what's the alternative to this kind of manual process? 27 | 28 | CODE. 29 | 30 | We can take a manual process like this, and turn it into an automated program, that will do all the heavy lifting for us. 31 | Computers are _very_ good at doing lots of sums, doing them quickly, and not making errors. 32 | 33 | > Something that's very important to remember: computers don't do what you want them to do, they do what you _tell_ them do. When computers give the wrong answer, a human error has been made somewhere - either in the writing of the program, or the operation of it. 34 | 35 | ## A simple diagram 36 | 37 | So let's take our engineering problem, and draw up a simple diagram expressing what it looks like, and what we want to work out: 38 | 39 | 40 | 41 | We have our wall, with 5 support nodes along the base and their reaction forces. We also have the length of the wall along the base, and we know that the 42 | >For this part of the course, I've just made up these values. Later on, when you've learned how to work with the SkyCiv API, have a go at using the code we write in these lessons on a real SkyCiv model! 43 | 44 | With that drawn up, it's pretty clear we'll need a list of the nodal reaction forces: 45 | 46 | ```python 47 | f1 = 5.6 48 | f2 = 4.3 49 | f3 = 3.6 50 | f4 = 2.8 51 | f5 = 4.1 52 | ``` 53 | 54 | and a list of the distances of those nodes, measured from some origin (in this case, the left hand side of the wall): 55 | 56 | ```python 57 | d1 = 0.0 58 | d2 = 0.75 59 | d3 = 1.5 60 | d4 = 2.25 61 | d5 = 3.0 62 | ``` 63 | 64 | That's the data we need to start coding. Now we need to know how to represent those numbers in code and how to work with them, which brings us nicely to our first lesson: `Variables`. -------------------------------------------------------------------------------- /lessons/00-our-engineering-problem/wall-in-context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyciv/intro-to-programming-and-api/28379a205e6ee5a735b435150219d387013707b7/lessons/00-our-engineering-problem/wall-in-context.png -------------------------------------------------------------------------------- /lessons/01-variables-and-operations/README.md: -------------------------------------------------------------------------------- 1 | # Variables and Operations 2 | 3 | ## Our starting data 4 | 5 | Let's just take a moment to remind ourselves of the starting data: 6 | ```python 7 | # Forces: 8 | f1 = 5.6 9 | f2 = 4.3 10 | f3 = 3.6 11 | f4 = 2.8 12 | f5 = 4.1 13 | 14 | # Distances from the left hand side: 15 | d1 = 0.0 16 | d2 = 0.75 17 | d3 = 1.5 18 | d4 = 2.25 19 | d5 = 3.0 20 | ``` 21 | 22 | What we've done above, in that code, is define 10 variables, f1-f5 & d1-d5, and set their values. 23 | 24 | We can now use those variables to calculate the total force, by adding the values together. 25 | 26 | We need somewhere to store the value of that force, so we define a variable. We can simultaneously assign a value to that variable. And in this case, we will assign the sum of the 5 forces we have: 27 | ```python 28 | total_force = f1 + f2 + f3 + f4 + f5 29 | ``` 30 | >💡 When we write the variables f1, f2, etc. in our piece of code, we are saying "use the value of f1, f2, etc. here". 31 | 32 | We can then show the user this value by printing it to the command line. 33 | 34 | ```python 35 | print('The total force is: ' + str(total_force) + 'kN') 36 | ``` 37 | 38 | >💡 The print statement also reveals something about our variables. They have a `type` - our forces and distances are numbers, in this case `floats`. We want to print a `string` to the command line. So we must use the `str()` function to turn our numerical value into a string. 39 | 40 | To calculate the moment about the midpoint, we first find the midpoint from the smallest and largest distances: 41 | ```python 42 | midpoint = (d5 - d1) / 2.0 43 | ``` 44 | 45 | We can then calculate in turn, the effect of each force on the moment: 46 | 47 | ```python 48 | # For the first force: 49 | total_moment = f1 * (midpoint - d1) 50 | 51 | # For the second force: 52 | total_moment = total_moment + f2 * (midpoint - d2) 53 | ``` 54 | NOTE that the code we write defies typical mathematical laws. 55 | A variable can appear on both sides of the '=' sign. 56 | The right hand side of '=' will be evaluated first, and then assigned to the left hand side. 57 | 58 | This operation is so common, that python has a convenient shorthand for this: `+=`. Applied to the 3rd force, that looks like: 59 | ```python 60 | # For the third force 61 | total_moment += f3 * (midpoint - d3) 62 | ``` 63 | 64 | NOTE: The exact syntax of '+=', '-=', '*=' & '/=' is language specific, but these kinds of operations are supported in many modern programming languages. 65 | 66 | We can finish the calculation of the total moment, and print it as well: 67 | ```python 68 | total_moment += f4 * (midpoint - d4) # fourth force 69 | total_moment += f5 * (midpoint - d5) # fifth force 70 | 71 | print('The total moment is: ' + str(total_moment) + 'kNm') 72 | ``` -------------------------------------------------------------------------------- /lessons/01-variables-and-operations/variables-and-operations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.9.1-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3.9.1 64-bit", 19 | "metadata": { 20 | "interpreter": { 21 | "hash": "549b59871d6a6b7c4f97b4e77ee4818a1e547e59fd095773d5c87a59b4471309" 22 | } 23 | } 24 | } 25 | }, 26 | "nbformat": 4, 27 | "nbformat_minor": 2, 28 | "cells": [ 29 | { 30 | "cell_type": "code", 31 | "execution_count": 11, 32 | "metadata": {}, 33 | "outputs": [ 34 | { 35 | "output_type": "stream", 36 | "name": "stdout", 37 | "text": [ 38 | "The total force is: 20.4 kN\n" 39 | ] 40 | } 41 | ], 42 | "source": [ 43 | "f1 = 5.6\n", 44 | "f2 = 4.3\n", 45 | "f3 = 3.6\n", 46 | "f4 = 2.8\n", 47 | "f5 = 4.1\n", 48 | "\n", 49 | "total_force = f1 + f2 + f3 + f4 + f5\n", 50 | "\n", 51 | "print('The total force is: ' + str(total_force) + 'kN')" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 12, 57 | "metadata": {}, 58 | "outputs": [ 59 | { 60 | "output_type": "stream", 61 | "name": "stdout", 62 | "text": [ 63 | "midpoint = 1.5 m\n" 64 | ] 65 | } 66 | ], 67 | "source": [ 68 | "d1 = 0.0\n", 69 | "d2 = 0.75\n", 70 | "d3 = 1.5\n", 71 | "d4 = 2.25\n", 72 | "d5 = 3.0\n", 73 | "\n", 74 | "midpoint = (d5 - d1) / 2.0\n", 75 | "\n", 76 | "print('midpoint = ' + str(midpoint) + ' m')" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 13, 82 | "metadata": {}, 83 | "outputs": [ 84 | { 85 | "output_type": "stream", 86 | "name": "stdout", 87 | "text": [ 88 | "moment = 8.399999999999999 kNm\n" 89 | ] 90 | } 91 | ], 92 | "source": [ 93 | "# For the first force:\n", 94 | "total_moment = f1 * (midpoint - d1)\n", 95 | "print ('moment = ' + str(total_moment) + ' kNm')" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 14, 101 | "metadata": {}, 102 | "outputs": [ 103 | { 104 | "output_type": "stream", 105 | "name": "stdout", 106 | "text": [ 107 | "moment = 11.624999999999998 kNm\n" 108 | ] 109 | } 110 | ], 111 | "source": [ 112 | "# For the second force:\n", 113 | "total_moment = total_moment + f2 * (midpoint - d2)\n", 114 | "print ('moment = ' + str(total_moment) + ' kNm')" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 15, 120 | "metadata": {}, 121 | "outputs": [ 122 | { 123 | "output_type": "stream", 124 | "name": "stdout", 125 | "text": [ 126 | "moment = 11.624999999999998 kNm\n" 127 | ] 128 | } 129 | ], 130 | "source": [ 131 | "total_moment += f3 * (midpoint - d3)\n", 132 | "print ('moment = ' + str(total_moment) + ' kNm')" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": 16, 138 | "metadata": {}, 139 | "outputs": [ 140 | { 141 | "output_type": "stream", 142 | "name": "stdout", 143 | "text": [ 144 | "moment = 3.374999999999999 kNm\n" 145 | ] 146 | } 147 | ], 148 | "source": [ 149 | "total_moment += f4 * (midpoint - d4) # fourth force\n", 150 | "total_moment += f5 * (midpoint - d5) # fifth force\n", 151 | "print ('moment = ' + str(total_moment) + ' kNm')" 152 | ] 153 | } 154 | ] 155 | } -------------------------------------------------------------------------------- /lessons/02-collections/README.md: -------------------------------------------------------------------------------- 1 | # Collections 2 | 3 | In the previous example, we used 5 separate values for the forces along the base of the wall (f1 to f5), and 5 separate values for the distances of these forces (d1 to d5) from the left hand side. 4 | 5 | Collections allow us to store multiple values in a single variable, and then manipulate those values. 6 | 7 | > Every programming language has various types of collections, and each collection has a specific purpose. The characteristics which differ between collections are things like:
(i) whether the values in the collections are ordered (and preserve the order between operations)
(ii) whether a value can appear more than once in the collection (whether duplicate values are permitted)
(iii) whether values can be added or removed from the collection
8 | 9 | > Some examples of collections (from various languages) are: `array`, `list`, `arraylist`, `dictionary`, `hashset`, `stack`, `concurrentbag`, etc.
10 | 11 | We'll stick with lists for now (the simplest collection in python), because they are more than adequate for our current application. 12 | 13 | A list is an ordered collection of values. 14 | We define a list (as a variable) using square brackets `[]`: 15 | ```python 16 | f = [5.6, 4.3, 3.6, 2.8, 4.1] # forces 17 | d = [0.0, 0.75, 1.5, 2.25, 3.0] # distances 18 | ``` 19 | We can get a value from the list by using its index to 'look it up': 20 | ```python 21 | f4 = f[3] 22 | ``` 23 | Tthe indexing starts from 0, so the first value in the list is `f[0]`: 24 | ```python 25 | f1 = f[0] 26 | f2 = f[1] 27 | f3 = f[2] 28 | # and so on ... 29 | ``` 30 | A nice feature in python is that we can get values starting from the end of the list, using negative numbers: 31 | ```python 32 | f5 = f[-1] 33 | ``` 34 | 35 | We can also change the values in a list by assigning a new value to a specific index. 36 | For example, we could ignore the force near the middle by making it 0: 37 | ```python 38 | f[2] = 0.0 39 | ``` 40 | Similarly we can change a number of values simultaneously, like making all the forces on the left = 0: 41 | ```python 42 | f[0:2] = 0.0 43 | ``` 44 | 45 | Collections are especially useful when used in conjunction with loops, which we'll discuss in the next lesson. 46 | Without loops, we can access the values in the list, and calculate our total force & moment using the list values. 47 | Remembering our lists from earlier: 48 | ```python 49 | f = [5.6, 4.3, 3.6, 2.8, 4.1] # forces 50 | d = [0.0, 0.75, 1.5, 2.25, 3.0] # distances 51 | ``` 52 | For the total force, we just sum the values: 53 | ```python 54 | ftot = f[0] + f[1] + f[2] + f[3] + f[4] 55 | ``` 56 | For the total moment, we sum the product of the force and distance from the midpoint: 57 | ```python 58 | mid = (d[-1] - d[0]) / 2.0 # NOTE how we use the -1 index to get the last item in the list. This has the benefit of working for any list, of any length 59 | mtot = f[0] * (mid - d[0]) + f[1] * (mid - d[1]) + f[2] * (mid - d[2]) + f[3] * (mid - d[3]) + f[4] * (mid - d[4]) 60 | ``` 61 | 62 | ## Manipulating the content of lists 63 | 64 | We can also add, remove and insert values in the list, using append, remove, pop and insert: 65 | ```python 66 | f.append(1.7) # adds an item to the end of the list. Here, 1.7 is the new item that we want to add. 67 | f.remove(3.6) # removes the first matching item in the list. Here, 3.6 is the item we want to find in the list and then remove. 68 | f.pop(2) # removes the item from the list at the index. Here, 2 is the index of the item we want to remove. The last item can be removed by omitting the index or supplying -1. 69 | f.insert(0, 5.9) # 0 is the index at which we want to insert the item, 5.9 is the item we want to insert. 70 | ``` -------------------------------------------------------------------------------- /lessons/02-collections/collections.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.9.1-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3.9.1 64-bit", 19 | "metadata": { 20 | "interpreter": { 21 | "hash": "549b59871d6a6b7c4f97b4e77ee4818a1e547e59fd095773d5c87a59b4471309" 22 | } 23 | } 24 | } 25 | }, 26 | "nbformat": 4, 27 | "nbformat_minor": 2, 28 | "cells": [ 29 | { 30 | "cell_type": "code", 31 | "execution_count": 3, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "# Defining a list using []\n", 36 | "f = [5.6, 4.3, 3.6, 2.8, 4.1]\t\t# forces\n", 37 | "d = [0.0, 0.75, 1.5, 2.25, 3.0]\t\t# distances" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 4, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "# look up a value\n", 47 | "f4 = f[3]" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "# indexing starts from 0, so:\n", 57 | "f1 = f[0]\n", 58 | "f2 = f[1]\n", 59 | "f3 = f[2]" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# we can also traverse the list backwards\n", 69 | "f5 = f[-1]" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "# set a single value\n", 79 | "f[2] = 0.0" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [ 88 | "# set part of the list to the same value\n", 89 | "f[0:2] = 0.0" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": null, 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [ 98 | "# reset our lists to their earlier values:\n", 99 | "f = [5.6, 4.3, 3.6, 2.8, 4.1]\t\t# forces\n", 100 | "d = [0.0, 0.75, 1.5, 2.25, 3.0]\t\t# distances" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "# Calculate the total force\n", 110 | "ftot = f[0] + f[1] + f[2] + f[3] + f[4]\n", 111 | "print('The total force is ' + str(ftot) + 'kN')" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 8, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "# For the total moment, start by getting the midpoint\n", 121 | "mid = (d[-1] - d[0]) / 2.0 # NOTE use of -1\n", 122 | "\n", 123 | "# calculate the total moment\n", 124 | "mtot = f[0] * (mid - d[0])\n", 125 | "mtot += f[1] * (mid - d[1]) # NOTE remember += operator\n", 126 | "mtot += f[2] * (mid - d[2])\n", 127 | "mtot += f[3] * (mid - d[3])\n", 128 | "mtot += f[4] * (mid - d[4]) \n", 129 | "print('The total moment is ' + str(mtot) + 'kNm')" 130 | ] 131 | } 132 | ] 133 | } -------------------------------------------------------------------------------- /lessons/03-loops/README.md: -------------------------------------------------------------------------------- 1 | # Loops 2 | 3 | Loops allow us to repeat an operation (or several operations) a number of times. 4 | We can combine loops with lists to perform the operations for each item in the list. 5 | 6 | Recalling our list of forces and list of distances: 7 | ```python 8 | f = [5.6, 4.3, 3.6, 2.8, 4.1] # forces 9 | d = [0.0, 0.75, 1.5, 2.25, 3.0] # distances 10 | ``` 11 | 12 | We have 5 items in our list, so we want to perform our calculation for force and moment 5 times. 13 | 14 | We can run a loop with 5 iterations to calculate the total force: 15 | ```python 16 | indexes = [0, 1, 2, 3, 4] 17 | for i in indexes: 18 | f_tot += f[i] # sum the forces (remember our += operator from Lesson 1) 19 | ``` 20 | 21 | >💡 Some lingo - The text indented under the for statement is the loop `body`. This is the set of operations that are performed at each `iteration` of the loop.
The operations **must** be indented to be recognised as the loop `body` in python. In other languages the `body` is often identified by a pair of braces {} after the for statement. 22 | 23 | This is basically an automated way of doing what we did in the previous lesson: 24 | ```python 25 | f_tot = f[0] + f[1] + f[2] + f[3] + f[4] 26 | ``` 27 | 28 | We can do the same thing for the total moment. 29 | First however, for efficiency, let's calculate the midpoint before running the loop: 30 | ```python 31 | mid = (d[-1] - d[0]) / 2 32 | ``` 33 | Furthermore, rather than writing out the indexes we want to use, 34 | let's use the native python function 'range' to construct the list of indexes for us: 35 | ```python 36 | for i in range(5): 37 | m_tot += f[i] * (mid - d[i]) # sum the products of the force & distance 38 | ``` 39 | Again, this is just like what we did manually in the previous lesson. 40 | 41 | The range function allows us to construct a list of indexes to loop through. We can define the `start` value of the loop, the value at which we want it to `stop` (and which should not be executed), and the `step` size - the difference between one index and the next. 42 | ```python 43 | range(0, 5, 1) = [0, 1, 2, 3, 4] # start at 0, stop at (before) 5, step by 1 44 | range(5) = [0, 1, 2, 3, 4] # because the start value and step size are optional, we can omit them and get the same list 45 | range(4,-1,-1) = [4, 3, 2, 1, 0] # we can step through the list the backwards and count down instead using step = -1 46 | range(2,9,2) = [2, 4, 6, 8] # with the right combination of start, stop & step values, we can create all kinds of lists 47 | ``` 48 | 49 | However, we're still not making full use of the power of loops combined with collections. Take a look again at our loops. In both cases we instructed the loop to run 5 times. 50 | 51 | What if we have a list with more or fewer values? 52 | We can accommodate this using the native python function 'len' to get the length of (_number of items in_) the list: 53 | ```python 54 | n = len(f) 55 | ``` 56 | and use the range keyword to construct an array of indexes to run the loop with: 57 | ```python 58 | for i in range(n): 59 | f_tot += f[i] 60 | m_tot += f[i] * (mid - d[i]) 61 | ``` 62 | 63 | > ⏱ Another improvement to think about in our code, is to consider speed. Earlier, we used 2 loops, each comprising 5 iterations. So in total, we performed 10 iterations. Furthermore, there is a performance overhead in setting up the loop - extending execution time further. Since our calculations for total force and total moment are independent of each other, In the above for block, we can do both calculations at the same time, within one loop. This is what we've done in the code above, and it nearly halves the execution time 👍 -------------------------------------------------------------------------------- /lessons/03-loops/loops.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.9.1-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3.9.1 64-bit", 19 | "metadata": { 20 | "interpreter": { 21 | "hash": "549b59871d6a6b7c4f97b4e77ee4818a1e547e59fd095773d5c87a59b4471309" 22 | } 23 | } 24 | } 25 | }, 26 | "nbformat": 4, 27 | "nbformat_minor": 2, 28 | "cells": [ 29 | { 30 | "cell_type": "code", 31 | "execution_count": 1, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "# Recall our input data\n", 36 | "f = [5.6, 4.3, 3.6, 2.8, 4.1]\t\t# forces\n", 37 | "d = [0.0, 0.75, 1.5, 2.25, 3.0]\t\t# distances" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "# Run a loop to calculate the total force\n", 47 | "indexes = [0, 1, 2, 3, 4]\n", 48 | "for i in indexes:\n", 49 | "\tftot += f[i] # NOTE remember += operator\n", 50 | "\n", 51 | "print('The total force is ' + str(ftot) + ' kN')" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "# Calculate the midpoint\n", 61 | "mid = d[-1] - d[0]\n", 62 | "\n", 63 | "# use range to run the loop\n", 64 | "for i in range(5):\n", 65 | " mtot += f[i] * (mid - d[i])\n", 66 | "\n", 67 | "print('The total moment is ' + str(mtot) + ' kN')" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "# Use len to determine the number of iterations\n", 77 | "n = len(f)\n", 78 | "\n", 79 | "# run the loop for the whole list\n", 80 | "for i in range(n):\n", 81 | "\tftot += f[i]\n", 82 | "\tmtot += f[i] * (mid - d[i])\n", 83 | "\n", 84 | "print('The total force is ' + str(ftot) + ' kN')\n", 85 | "print('The total moment is ' + str(mtot) + ' kN')" 86 | ] 87 | } 88 | ] 89 | } -------------------------------------------------------------------------------- /lessons/04-flow-control-and-if-statements/README.md: -------------------------------------------------------------------------------- 1 | # Flow control - 'If' statements 2 | 3 | The next thing we want to do is check whether the total force we have calculated exceeds the bearing capacity of the foundation under the wall. 4 | 5 | To do this, we can use an `if` statement, and alert the user if the foundation is not strong enough. 6 | 7 | An `if` statement allows us to instruct the program to process certain code, and ignore other code, depending on some criteria that we specify. 8 | 9 | Let's look at this by first defining the force capacity of the foundation: 10 | ```python 11 | f_cap = 100 # set this value to whatever you want 12 | ``` 13 | and the value of total force: 14 | ```python 15 | f_tot = 10 # again, set this value ot whatever you want 16 | ``` 17 | With those 2 values, our `if` statement looks like: 18 | ```python 19 | if f_tot > f_cap: 20 | print("force exceeds the capacity!") 21 | ``` 22 | we can also add an "else if" statement using `elif`: 23 | ```python 24 | elif f_tot == f_cap: 25 | print("force is equal to capacity") 26 | ``` 27 | 28 | If the first criterion is met, the `elif` condition will not be checked. If the first criterion is **not** met, the criterion in `elif` will be checked next. 29 | 30 | > 💡 When we want to check whether a value equals another, we use two `=` signs. This distinguishes checking equality from assigning a value to the variable. 31 | 32 | Finally, we can add an else statement. If none of the conditions in `if` or `elif` are met 33 | this code block will be processed. 34 | ```python 35 | else: 36 | print("force is within capacity") 37 | ``` 38 | all together that looks like: 39 | ```python 40 | if f_tot > f_cap: 41 | print("force exceeds the capacity!") 42 | elif f_tot == f_cap: 43 | print("force is equal to capacity") 44 | else: 45 | print("force is within capacity") 46 | ``` 47 | 48 | ## Accuracy of calculations on computers 49 | 50 | One thing to note when comparing non-integer numbers in programming code, is the calculations are done with floating point precision. 51 | What this basically means, is that numbers can be guaranteed to be accurate to only 15 significant figures. 52 | So you could define a variable like 10.0, but when saved to memory, this variable will get slightly distorted. When you subsequently print this variable, you could see something like 10.0000000000004. 53 | 54 | If you compare that value to 10.0 using `==` what's going to happen? The `if` statement will tell you that those numbers are not equal. But as engineers, we are comfortable accepting these values are equal - that tiny 0.0000000000004 makes no difference to quantities like 100s of kNs of force. 55 | 56 | So, rather than comparing these values using `==`, we should compare their difference to some level of tolerance with which we are happy: 57 | 58 | ```python 59 | 60 | # compare the difference in force to a small tolerance 61 | if (f_cap - f_tot) > 1.0E-6: 62 | print("force exceeds the capacity!") 63 | else if abs(f_cap - f_tot) < 1.0E-6: 64 | print("force is equal to capacity") 65 | else: 66 | print("force is within capacity") 67 | ``` -------------------------------------------------------------------------------- /lessons/04-flow-control-and-if-statements/flow-control-and-if-statements.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": 3 14 | }, 15 | "orig_nbformat": 2 16 | }, 17 | "nbformat": 4, 18 | "nbformat_minor": 2, 19 | "cells": [ 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "fcap = 100 # set this value to whatever you want\n", 27 | "ftot = 200 # set this value to whatever you want\n", 28 | "\n", 29 | "if ftot > fcap:\n", 30 | "\tprint(\"bearing force exceeds the capacity!\")" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "ftot = 100\n", 40 | "if ftot > fcap:\n", 41 | "\tprint(\"force exceeds the capacity!\")\n", 42 | "elif ftot == fcap:\n", 43 | "\tprint(\"force is equal to capacity\")" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "ftot = 50\n", 53 | "if ftot > fcap:\n", 54 | "\tprint(\"force exceeds the capacity!\")\n", 55 | "elif ftot == fcap:\n", 56 | "\tprint(\"force is equal to capacity\")\n", 57 | "else:\n", 58 | "\tprint(\"force is within capacity\")" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "fcap = 100 # set this value to whatever you want\n", 68 | "ftot = 10 # set this value to whatever you want\n", 69 | "\n", 70 | "# compare the difference in force to a small tolerance\n", 71 | "if (fcap - ftot) > 1.0E-6:\n", 72 | "\tprint(\"force exceeds the capacity!\")\n", 73 | "else if abs(f_cap - f_tot) < 1.0E-6:\n", 74 | "\tprint(\"force is equal to capacity\")\n", 75 | "else:\n", 76 | "\tprint(\"force is within capacity\")" 77 | ] 78 | } 79 | ] 80 | } -------------------------------------------------------------------------------- /lessons/05-functions/README.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | In the previous lesson we checked the force against the capacity. We can do a similar check, and compare the overturning moment to the foundation _moment_ capacity. 4 | 5 | Remembering our force against capacity calculation: 6 | 7 | ```python 8 | f_cap = 100 9 | f_tot = 10 10 | 11 | if (f_cap - f_tot) > 1.0E-6: 12 | print("force exceeds the capacity!") 13 | else if abs(f_cap - f_tot) < 1.0E-6: 14 | print("force is equal to capacity") 15 | else: 16 | print("force is within capacity") 17 | ``` 18 | 19 | Our moment against capacity check would look like: 20 | 21 | ```python 22 | m_cap = 100 23 | m_tot = 10 24 | 25 | if (m_cap - m_tot) > 1.0E-6: 26 | print("moment exceeds the capacity!") 27 | else if abs(f_cap - f_tot) < 1.0E-6: 28 | print("moment is equal to capacity") 29 | else: 30 | print("moment is within capacity") 31 | ``` 32 | 33 | Notice anything? We have essentially written the same if statement twice, just with different variables, and slightly different text. 34 | 35 | This is where a `function` becomes very useful. 36 | A function allows us to reuse a block of code multiple times, without writing it out every time. 37 | It also gives us a single place to edit and maintain that code - 38 | if we want to change the behaviour, we only have to change it once, in one place. 39 | 40 | > 💡 If you find yourself writing a similar piece of code over and over, that's a good indication you might want to write a function. 41 | 42 | In python, we define a function with the `def` keyword, followed by the function name. 43 | The variables in the parentheses `()` are the function `arguments` - the values we must pass to the function for it to work. 44 | The indented text on the next line is the function `body`, which is the piece of code we want to run every time we use the function. 45 | 46 | ```python 47 | def check_against_capacity(tot, cap): 48 | if tot > cap: 49 | return "exceeds the capacity!" 50 | elif abs(tot - cap) < 1.0E-6: 51 | return "is equal to capacity" 52 | else: 53 | return "is within capacity" 54 | ``` 55 | 56 | We use the function by `call`ing it. We do this simply by using it in code. 57 | 58 | > 💡 We've been using functions since lesson 1 - we've used functions like `print()`, `str()`, `range()` and `len()`. 59 | 60 | Let's do this for the force against capacity check: 61 | ```python 62 | f_cap = 100 63 | f_tot = 10 64 | output = "force " + check_against_capacity(f_tot, f_cap) 65 | print(output) 66 | ``` 67 | 68 | We can use the function again, to check the moment against the capacity: 69 | 70 | ```python 71 | m_cap = 100 72 | m_tot = 10 73 | output = "moment " + check_against_capacity(m_tot, m_cap) 74 | print(output) 75 | ``` 76 | 77 | By using this function, we just reused 7 lines of code (twice), and it only used up 2 lines in our program! Functions can be really powerful for keeping code short, and minimising the time it takes to write it. -------------------------------------------------------------------------------- /lessons/05-functions/functions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.9.1-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3.9.1 64-bit", 19 | "metadata": { 20 | "interpreter": { 21 | "hash": "549b59871d6a6b7c4f97b4e77ee4818a1e547e59fd095773d5c87a59b4471309" 22 | } 23 | } 24 | } 25 | }, 26 | "nbformat": 4, 27 | "nbformat_minor": 2, 28 | "cells": [ 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "# Force check against capacity:\n", 36 | "\n", 37 | "fcap = 100\n", 38 | "ftot = 10\n", 39 | "\n", 40 | "if (f_cap - f_tot) > 1.0E-6:\n", 41 | "\tprint(\"force exceeds the capacity!\")\n", 42 | "else if abs(f_cap - f_tot) < 1.0E-6:\n", 43 | "\tprint(\"force is equal to capacity\")\n", 44 | "else:\n", 45 | "\tprint(\"force is within capacity\")\n", 46 | "\n", 47 | "# Moment check against capacity:\n", 48 | "\n", 49 | "mcap = 100\n", 50 | "mtot = 10\n", 51 | "\n", 52 | "if (m_cap - m_tot) > 1.0E-6:\n", 53 | "\tprint(\"moment exceeds the capacity!\")\n", 54 | "else if abs(f_cap - f_tot) < 1.0E-6:\n", 55 | "\tprint(\"moment is equal to capacity\")\n", 56 | "else:\n", 57 | "\tprint(\"moment is within capacity\")" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 1, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "# define the function\n", 67 | "def check_against_capacity(tot, cap):\n", 68 | "\tif tot > cap:\n", 69 | "\t\treturn \"exceeds the capacity!\"\n", 70 | "\telif abs(tot - cap) < 1.0E-6:\n", 71 | "\t\treturn \"is equal to capacity\"\n", 72 | "\telse:\n", 73 | "\t\treturn \"is within capacity\"" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 3, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "output_type": "stream", 83 | "name": "stdout", 84 | "text": [ 85 | "bearing force exceeds the capacity!\n" 86 | ] 87 | } 88 | ], 89 | "source": [ 90 | "# use the function to determine whether the force is within capacity\n", 91 | "fcap = 100 # set this value to whatever you like\n", 92 | "ftot = 10 # set this value to whatever you like\n", 93 | "output = \"force \" + check_against_capacity(ftot, fcap)\n", 94 | "print(output)" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": null, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "# use the function again to determine whether the moment is within capacity\n", 104 | "mcap = 100\n", 105 | "mtot = 10\n", 106 | "output = \"moment \" + check_against_capacity(mtot, mcap)\n", 107 | "print(output)" 108 | ] 109 | } 110 | ] 111 | } -------------------------------------------------------------------------------- /lessons/06-objects-and-properties/README.md: -------------------------------------------------------------------------------- 1 | # Objects 2 | 3 | So far we've worked with simple data. Storing single values in variables or with other values in a collection. 4 | But the data that comes back from modern structural analysis and design software, such as SkyCiv Structural 3D, is usually much more sophisticated than this. 5 | 6 | In our case, for each force along the bottom of the wall, we'd get back 3 components of the force, corresponding to all 3 degrees of freedom (X, Y & Z). 7 | 8 | Expressed in a simple way, that data might look something like this: 9 | ```python 10 | x: -0.3 11 | y: 0.8 12 | z: 5.6 13 | ``` 14 | Now we could express that using an array, where item 0 corresponds to the x direction, item 1 corresponds to the y direction, and item 2 corresponds to the z direction. 15 | 16 | A clearer and more flexible way to hold this data, is with an `object`. The most common object seen in programming languages is the `class`. 17 | 18 | ## Using Classes 19 | 20 | For our application, it's most useful for us to learn how to _use_ classes rather than the ins and outs of creating them.
21 | Nevertheless, we need to see the class definition and instantiation (see 💡 below) to know what's going on.
22 | Below is a `class` called _force_, with 3 `attributes`, 1 for each component of that force in the 3 DOFs.
23 | 24 | ```python 25 | class Force: 26 | def __init__(self, x, y, z): 27 | self.X = x 28 | self.Y = y 29 | self.Z = z 30 | 31 | def to_string(self): 32 | return str(self.X) + ', ' + str(self.Y) + ', ' + str(self.Z) 33 | ``` 34 | 35 | We can define a variable representing one `instance` of that class like so: 36 | 37 | ```python 38 | f1 = Force(-0.3, 0.8, 5.6) 39 | ``` 40 | 41 | >💡 The `class` `definition` is like a blueprint for the `class`. It represents the outline of what data is required, but doesn't represent the _actual_ set of values (much like in algebra, where a letter indicates a variable that can take on any value).
The actual set of values is represented by an `instance` of the `class`. If we have multiple forces, each force is an `instance` of the force class.
Creating an `instance` is called `instantiation`, but programmers will often refer to creating an instance of the class, and setting the _initial_ values, as `initializing`. 42 | 43 | We can get values from the class by using the variable and the _attribute_ we want to get, linked by a dot: 44 | 45 | ```python 46 | print('Force in X = ' + str(f1.X)) 47 | print('Force in Y = ' + str(f1.Y)) 48 | print('Force in Z = ' + str(f1.Z)) 49 | ``` 50 | 51 | Similarly, we can set values of attributes by placing _{variable}.{attribute}_ on the left hand side of the `=` operator: 52 | 53 | ```python 54 | f1.X = 0.1 55 | f1.Y = -0.1 56 | f1.Z = 0.0 57 | ``` 58 | 59 | We can also call functions on the object using a dot, the function name, and parentheses with the required arguments: 60 | 61 | ```python 62 | print('Force = ' + f1.to_string()) 63 | ``` 64 | 65 | In the context of our earlier engineering question, when we eventually work with the API, we will often get back lists of objects. 66 | These work in the same way as a list of values: 67 | 68 | ```python 69 | fs = [Force(-0.3, 0.8, 5.6), 70 | Force(0.1, -0.3, 4.3), 71 | Force(0.5, 0.7, 3.6), 72 | Force(-0.3, 0.6, 2.8), 73 | Force(0.0, -0.1, 4.1)] 74 | 75 | print('Force in Z = ' + str(fs[2].Z)) 76 | ``` 77 | 78 | We can sum up the forces in that list to find a total force, using a loop (like in Lesson 4): 79 | 80 | ```python 81 | f_tot = 0.0 82 | for i in range(len(fs)): 83 | f_tot += fs[i].Z 84 | 85 | print('Total Force = ' + str(f_tot)) 86 | ``` 87 | 88 | However, we can make that loop read a lot clearer, by looping through the forces, rather than using an index to look up the values: 89 | 90 | ```python 91 | f_tot = 0.0 92 | for f in fs: 93 | f_tot += f.Z 94 | 95 | print('Total Force = ' + str(f_tot)) 96 | ``` 97 | 98 | Furthermore, we can define `f_tot` not as a single value, but _of type_ `Force` instead. 99 | This means we can simultaneously sum all components of the force within the loop, and store them together on one force variable: 100 | 101 | ```python 102 | f_t = Force(0,0,0) 103 | for f in fs: 104 | f_t.X += f.X 105 | f_t.Y += f.Y 106 | f_t.Z += f.Z 107 | 108 | print('Total Force = ' + f_t.to_string()) 109 | ``` -------------------------------------------------------------------------------- /lessons/06-objects-and-properties/objects.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": 3 14 | }, 15 | "orig_nbformat": 2 16 | }, 17 | "nbformat": 4, 18 | "nbformat_minor": 2, 19 | "cells": [ 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "# Define the class\n", 27 | "class Force:\n", 28 | " def __init__(self, x, y, z):\n", 29 | " self.X = x\n", 30 | " self.Y = y\n", 31 | " self.Z = z\n", 32 | "\n", 33 | " def to_string(self):\n", 34 | " return str(self.X) + ', ' + str(self.Y) + ', ' + str(self.Z)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "# Create an instance of the class\n", 44 | "f1 = Force(-0.3, 0.8, 5.6)\n", 45 | "\n", 46 | "# Use the instance attributes in some print statements\n", 47 | "print('Force in X = ' + str(f1.X))\n", 48 | "print('Force in Y = ' + str(f1.Y))\n", 49 | "print('Force in Z = ' + str(f1.Z))" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "# Set the values of the class instance attributes\n", 59 | "f1.X = 0.1\n", 60 | "f1.Y = -0.1\n", 61 | "f1.Z = 0.0\n", 62 | "\n", 63 | "# Call functions from the class instance\n", 64 | "print('Force = ' + f1.to_string())" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": null, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "# Define a list of class instances\n", 74 | "fs = [Force(-0.3, 0.8, 5.6), \n", 75 | " Force(0.1, -0.3, 4.3), \n", 76 | " Force(0.5, 0.7, 3.6), \n", 77 | " Force(-0.3, 0.6, 2.8), \n", 78 | " Force(0.0, -0.1, 4.1)]\n", 79 | "\n", 80 | "# Access the attributes for one of the class instances\n", 81 | "print('Force in Z = ' + str(fs[2].Z))" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "# Add up the forces using a loop with numerical indexing\n", 91 | "f_tot = 0.0\n", 92 | "for i in range(len(fs)):\n", 93 | " f_tot += fs[i].Z\n", 94 | "\n", 95 | "print('Total Force = ' + str(f_tot))" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "# Add up the forces by using each class instance as the loop variable during the iteration\n", 105 | "f_tot = 0.0\n", 106 | "for f in fs:\n", 107 | " f_tot += f.Z\n", 108 | "\n", 109 | "print('Total Force = ' + str(f_tot))" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "# Add up the forces and store the total on another instance of the Force class\n", 119 | "f_t = Force(0,0,0)\n", 120 | "for f in fs:\n", 121 | " f_t.X += f.X\n", 122 | " f_t.Y += f.Y\n", 123 | " f_t.Z += f.Z\n", 124 | "\n", 125 | "print('Total Force = ' + f_t.to_string())" 126 | ] 127 | } 128 | ] 129 | } -------------------------------------------------------------------------------- /lessons/07-other-languages/README.md: -------------------------------------------------------------------------------- 1 | # Other languages - JavaScript 2 | 3 | Before we move on to working with JSON, http requests and the SkyCiv API, let's recap what we've learned a little bit while taking a look at another popular programming language for the web: `JavaScript`. 4 | 5 | What we're trying to get across here is that while the _syntax_ of particular languages varies, the same key concepts like `variables`, `collections`, `loops`, `ifs` and `objects` apply. Once you've got one language down, it's not a huge step to try your hand at another. 6 | 7 | >💡 "Syntax" pretty much means "how do we put words and letters together to make sentences", or in the context of programming, "how do we put words and letters together to make statements / expressions". 8 | 9 | ## Variables 10 | 11 | If you remember in the video lesson on variables we talked about how other languages require a keyword for declaring variables, well JavaScript is just one such language.
12 | We define variables in JavaScript with `var`: 13 | 14 | ```javascript 15 | var f1 = 5.6; 16 | var f2 = 4.3; 17 | var f3 = 3.6; 18 | var f4 = 2.8; 19 | var f5 = 4.1; 20 | 21 | var totalForce = f1 + f2 + f3 + f4 + f5; 22 | console.log("Force = " + totalForce); 23 | ``` 24 | 25 | You'll notice a couple of other things:
26 | 1. Each line ends with a semi-colon (`;`) 27 | 2. Variables with longer names (`totalForce`) are defined using `camelCase` - in python, we used `snake_case` 28 | 3. We use `console.log()` rather than `print` 29 | 4. We don't need to get a `string` representation of the `float` value `totalForce` - JavaScript will do this for us when concatenating the string. 30 | 31 | ## Collections 32 | 33 | Defining collections in JavaScript is simple. Just like in python, we use square brackets: 34 | 35 | ```javascript 36 | var fs = [5.6, 4.3, 3.6, 2.8, 4.1]; 37 | var f1 = fs[0]; 38 | fs[-1] = 0.0; // not supported - has no effect 39 | ``` 40 | 41 | >💡 Negative indices are **not** supported in JavaScript 42 | 43 | ## Loops 44 | 45 | Loops work similarly in JavaScript - we use them to repeat an operation or set of operations multiple times. 46 | The syntax in JavaScript starts with the `for` keyword, just as in python: 47 | 48 | ```javascript 49 | fs = [5.6, 4.3, 3.6, 2.8, 4.1]; 50 | var totalForce = 0; 51 | for (var i = 0; i < fs.length; i++) { 52 | totalForce += fs[i]; 53 | } 54 | 55 | console.log("Force = " + totalForce) 56 | ``` 57 | 58 | Otherwise, there are a few important differences we need to note: 59 | 1. The body of the loop is indicated by a pair of curly braces `{}` - everything between these braces will be executed for each iteration of the loop. Separate statements within the loop (on each line) are indicated with `;`, just like in other JavaScript code. 60 | 1. The loop definition requires us to declare a variable, in this case `i`, to be the _iterator_. 61 | 1. The stop condition comes next, and rather than being a value, is a logical statement based on the iterator variable (`i`). 62 | 1. Finally we must state how the iterator variable should change in value between iterations. In the case above, we put `i++`. `++` is another shorthand (like `+=`), which means increment the iterator by +1 for each new iteration. 63 | 64 | ## If statements 65 | 66 | If statements again look pretty similar in JavaScript when compared with python. We start the statement with the `if` keyword. What follows is the condition (or set of conditions) that are checked to determine if they are true or not. The condition(s) _must_ be enclosed in parentheses `()` to be recognised. 67 | 68 | Following the condition(s), a pair of curly braces `{}` indicates the operations to execute should the condition(s) evalute to true. This is similar to the loop body as above (also indicated with `{}`). 69 | 70 | We can add as many `else if` blocks as we like, to check further conditions, just like the `elif` blocks in python. Finally, we can add an `else` block, that will be executed if none of the `if` or `else if` blocks are executed. 71 | 72 | ```javascript 73 | var totalForce = 100; 74 | var capacity = 90; 75 | 76 | if (totalForce > capacity){ 77 | console.log("Force exceeds capacity!"); 78 | } 79 | else if (abs(totalForce - capacity) < 1.0E-6){ 80 | console.log("Force equals capacity"); 81 | } 82 | else { 83 | console.log("Force is within capacity"); 84 | } 85 | ``` 86 | 87 | ## Functions 88 | 89 | We can define functions in JavaScript just like we can in python. 90 | 91 | By now, the syntax will probably not surprise you: just like `loops` & `if` statements the function `body` is indicated by a pair of curly braces `{}`. 92 | 93 | The function `body` is preceded by the keyword '`function`'. The function name comes next, followed by the arguments of the function, which are contained within parentheses. And just like in python, we indicate the value to send back to the function call site with the `return` keyword: 94 | 95 | ```javascript 96 | function checkAgainstCapacity(total, capacity){ 97 | if (total > capacity){ 98 | return "exceeds capacity!"; 99 | } 100 | else if (abs(total - capacity) < 1.0E-6){ 101 | return "equals capacity"; 102 | } 103 | else { 104 | return "is within capacity"; 105 | } 106 | } 107 | 108 | console.log("Force " + checkAgainstCapacity(totalForce, capacity)); 109 | ``` 110 | 111 | ## Objects and Classes 112 | 113 | Finally we can show that JavaScript supports `objects` and `classes` as well. JavaScript objects and the _JavaScript Object Notation_ (JSON) can seem pretty similar and interchangeable. It's not _quite_ that simple, but we won't discuss it here - instead we tackle it in lesson 9. 114 | 115 | Class definitions look pretty similar in JavaScript, with some important differences: 116 | 117 | 1. We use the `constructor` keyword instead of `__init__` to define the function that is run when we _initialize_ the class 118 | 1. We use the `this` keyword instead of `self` to refer to the instance of the class inside the class itself 119 | 1. We do not use `def` to define functions (and we also don't need the `function` keyword like we did above) 120 | 121 | ```javascript 122 | class Force { 123 | constructor(x, y, z) { 124 | this.X = x; 125 | this.Y = y; 126 | this.Z = z; 127 | } 128 | 129 | toString() { 130 | return this.X + ', ' + this.Y + ', ' + this.Z; 131 | } 132 | } 133 | ``` 134 | 135 | Using classes is _mostly_ the same: 136 | 1. We can declare a variable to be of the type of our class. If we want to set the value by calling the `constructor`, we must use the `new` keyword (which is not needed in python). 137 | 1. Using the value of class properties is similarly done by typing `className` __dot__ `propertyName`, e.g. `totalForce.Fx`. 138 | 1. Defining an array of classes, and using them within a loop, works very much the same. 139 | 140 | ```javascript 141 | var f = new Force(-0.3, 0.8, 5.6); 142 | 143 | var fs = [new Force(-0.3, 0.8, 5.6), 144 | new Force(0.1, -0.3, 4.3), 145 | new Force(0.5, 0.7, 3.6), 146 | new Force(-0.3, 0.6, 2.8), 147 | new Force(0.0, -0.1, 4.1)]; 148 | 149 | var totalForce = new Force(0.0, 0.0, 0.0); 150 | for (var i = 0; i < fs.length; i++) { 151 | totalForce.X += fs[i].X; 152 | totalForce.Y += fs[i].Y; 153 | totalForce.Z += fs[i].Z; 154 | } 155 | ``` 156 | 157 | ## Extra content - array "prototype" methods & arrow functions 158 | 159 | One extra cool feature of JavaScript that I find myself using a lot is _lambda functions_, especially those on arrays (referred to as array prototypes). 160 | 161 | Carrying on from the objects example above, we can rewrite that last loop using `forEach`. This is a special method which runs a loop, and at each 'iteration' executes a function that we define within the parentheses of the `forEach` statement. 162 | 163 | In the following example, we define the function using the `arrow function` notation: 164 | 165 | ```javascript 166 | var totalForce = new Force(0.0, 0.0, 0.0,); 167 | fs.forEach(f => { 168 | totalForce.X += f.X; 169 | totalForce.Y += f.Y; 170 | totalForce.Z += f.Z; 171 | }) 172 | 173 | console.log('totalForce = ' + totalForce.toString()); 174 | ``` 175 | 176 | The arrow function is defined by `iterator => {body}`. It's a nice shorthand for defining a short function to run at each iteration of the `forEach` loop. 177 | 178 | Don't worry if this is a little confusing - this is a more advanced programming topic - but it shows the power built into modern programming languages such as JavaScript. 179 | 180 | Similar awesome features exist in python too! -------------------------------------------------------------------------------- /lessons/08-environment-setup/README.md: -------------------------------------------------------------------------------- 1 | # environment-setup 2 | 3 | ## VSCode 4 | 5 | Visual Studio Code (VSCode) is essentially a supercharged text editor. It provides a bunch of great tools to help us code more efficiently. 6 | 7 | There are loads of great extensions that are available for VSC. We will look at some of these in the video. 8 | 9 | Download: https://code.visualstudio.com/download 10 | 11 | ## node.js 12 | 13 | Traditionally JavaScript only worked in the browser. To allow the use of JavaScript for a server, node.js was created. It allows us to write programs that will run in a console. 14 | 15 | Download: https://nodejs.org/en/download/ 16 | 17 | ## Python 18 | 19 | Python is a _high level_ programming language which means it is closer to the way humans speak compared to other languages. It is typically used to write command line applications however there are frameworks that allow you to use it to build websites. 20 | 21 | Download: https://www.python.org/downloads/ -------------------------------------------------------------------------------- /lessons/09-json-basics-and-api/README.md: -------------------------------------------------------------------------------- 1 | # json basics and api 2 | 3 | ## What is JSON? 4 | 5 | JSON is an acronym for JavaScript Object Notation. It is not to be confused with an `object` or `dictionary`. 6 | 7 | JSON was introduced as a data-exchange format. It quickly became a popular way to send data to different machines across various languages. 8 | 9 | It is *language independent*. This means, **it doesn't belong to any language**, however, it was based on the C-family of languages. 10 | 11 | It's easily readable for humans and very easy to "parse" for machines. 12 | 13 | JSON can be formed using two types of structures: 14 | 15 | - A collection of key/value pairs. Often referred to in other languages as an object, struct, dictionary, hash table, etc. 16 | 17 | e.g: `"force_type": "point_load"` 18 | 19 | - An ordered list of values. Often referred to in other languages as an array, list, vector, sequence, etc. 20 | 21 | e.g: `"member_ids": [1, 4, 6]` - this is guaranteed to retain the order that the values are listed. 22 | 23 | ### What does it look like? 24 | 25 | JSON looks very similar to a JavaScript Object (essentially identical) or Python Dictionary. 26 | 27 | Here is a small piece of JSON that we will see again in an upcoming lesson. This is a real piece of a SkyCiv API model Object 28 | 29 | ```json 30 | { 31 | "plates": { 32 | "1": { 33 | "nodes": [4, 5, 7, 6], 34 | "thickness": 50, 35 | "material_id": 1, 36 | "rotZ": 0, 37 | "type": "mindlin", 38 | "offset": 65.6, 39 | "state": "stress", 40 | "is_meshed": true 41 | } 42 | } 43 | } 44 | ``` 45 | 46 | A few things to note: 47 | * The entire JSON is wrapped inside curly braces `{}`. 48 | * Every `key` is wrapped in double quotes: `"nodes": ...` 49 | * Every level of indentation indicates that those key-value pairs are inside the outer object. 50 | 51 | Because `"nodes"`, `"thickness"` etc are all at the same level of indentation, this indicates that they are all inside the key `"1"` and `"1"` is a child of `"plates"`. Once you notice that the value associated to a key can be an object, then you realise that in theory, the object can go down to many sub-levels. 52 | 53 | If we were to add another plate with an ID of `"2"`, it would be a child of the plates object. 54 | 55 | ```json 56 | { 57 | "plates": { 58 | "1": { 59 | "nodes": [4, 5, 7, 6], 60 | "thickness": 50, 61 | // etc... 62 | }, 63 | "2": { 64 | "nodes": [7, 6, 9, 8], 65 | "thickness": 20, 66 | // etc... 67 | } 68 | } 69 | } 70 | ``` 71 | 72 | It's also important to see that we had to add a comma `","` after the first item `"1"`. This indicates we are adding more objects. 73 | 74 | A great way to confirm you are formatting your JSON correctly is by installing the VSCode plugin "Prettier". Paste this into the search bar in the VSCode Extensions tab: `esbenp.prettier-vscode`. Prettier will format the document depending on what file type you have selected in the far bottom right of the VSCode editor. This will default to the file extension such as `.py` or `.js`. 75 | 76 | ## What is an API? 77 | An Application Programming Interface (API) is a way of communicating with a server from any coding environment. 78 | 79 | Think of a website that compares multiple airline prices. When you go to their website and ask: 80 | 81 | > Hey, I want to book a flight to this place at this time. What's the cheapest option? 82 | 83 | where do they get all this information? Have you ever thought about this? 84 | 85 | The answer is that every airline they check, has an API. This means the airline has set up a URL that anyone can send some data to describing their question and it will response with the requested data. 86 | 87 | So the comparison website doesn't navigate to each website and look at the prices for your flight, instead they ask the question to the airline's API! 88 | 89 | ### SkyCiv API 90 | So what if you wanted to solve a structural model without opening any program or website? Well you can now make a peice of data which describes a structural model and send it to the SkyCiv API! It can perform loads of actions and response with various data for you to work with. 91 | 92 | -------------------------------------------------------------------------------- /lessons/09-json-basics-and-api/api-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyciv/intro-to-programming-and-api/28379a205e6ee5a735b435150219d387013707b7/lessons/09-json-basics-and-api/api-diagram.png -------------------------------------------------------------------------------- /lessons/10-sending-json/README.md: -------------------------------------------------------------------------------- 1 | # sending json 2 | 3 | ## How do we actually create JSON? 4 | 5 | To understand how to create JSON, it is best that we consider the process of sending and receiving data. 6 | 7 | **So consider this scenario:** 8 | 9 | * We have a language specific object. 10 | * We want to send this information (the object) to a url and get a response via a HTTP request. 11 | * We know the server at this url will know what to do with this object and it will then send information back. 12 | 13 | **The next thing to think about is what is a HTTP request?** 14 | 15 | HTTP means `Hypertext Transfer Protocol`. A bunch of big words but the main thing to realise here is that it is a way of sending text, **not objects!** 16 | 17 | **JSON to the rescue!** 18 | 19 | JSON uses a format that can easily be converted to a string (text) and also easily be **parsed** back to an object. 20 | 21 | Coding languages typically have built in functions that will handle converting your objects to and from JSON. 22 | 23 | --- 24 | 25 | ## Examples 26 | 27 | If you're still struggling with the difference between language objects and JSON, hopefully the difference between the following JavaScript and Python examples will make it clear! 28 | 29 | We will include a boolean and an empty value to see the difference in the languages: 30 | 31 | ### JavaScript Example 32 | ```javascript 33 | const plates = { 34 | plates: { 35 | 1: { 36 | nodes: [4, 5, 7, 6], 37 | thickness: 50, 38 | is_meshed: true, 39 | some_empty_value: null 40 | }, 41 | }, 42 | }; 43 | 44 | const platesToJson = JSON.stringify(plates); 45 | ``` 46 | 47 | After using `JSON.stringify` on the object, `platesToJson` now contains the string: 48 | 49 | `"{"plates":{"1":{"nodes":[4,5,7,6],"thickness":50,"is_meshed":true,"some_empty_value":null}}}"` 50 | 51 | *Note:* If you see a bunch of backslashes scatter through this string when you print this yourself, they are just "escape characters", it won't affect the code. 52 | 53 | --- 54 | 55 | ### Python Example 56 | 57 | Now in Python, `null` does not exist. Instead, the equivalent is `None`. Also, booleans are capitalised! 58 | 59 | Compare the difference between this Python dictionary and the previous JavaScript Object. In particular `null` vs `None` and `true` vs `True`. 60 | 61 | ```py 62 | import json 63 | 64 | plates = { 65 | "plates": { 66 | "1": { 67 | "nodes": [4, 5, 7, 6], 68 | "thickness": 50, 69 | "is_meshed": True, 70 | "some_empty_value": None 71 | }, 72 | }, 73 | } 74 | 75 | plates_to_json = json.dumps(plates) 76 | ``` 77 | 78 | But after using Python's `json` library denoted by the `import json` at above the dictionary, the variable `plates_to_json` becomes: 79 | 80 | `"{"plates": {"1": {"nodes": [4, 5, 7, 6], "thickness": 50, "is_meshed": true, "some_empty_value": null}}}"` 81 | 82 | Which is the same as the JavaScript json string! Although Python doesn't trim the whitespaces which is not an issue. 83 | 84 | --- 85 | 86 | ### Sending a request 87 | 88 | There are a few ways to make a HTTP request. We encourage using our NPM, Pip or NuGet package which you can [read more about here](https://skyciv.com/api/v3/docs/packages/). This page also walks you through setting up a project to use these packages. They reduce the amount of coding to a fraction of traditional ways. 89 | 90 | #### Using SkyCiv package 91 | The file [skycivCall.js](./skycivCall.js) shows you how to make the request using the `skyciv` NPM package. 92 | The file [skycivCall.py](./skycivCall.py) shows you how to make the request using the `skyciv` Pip package. 93 | 94 | #### Without SkyCiv package 95 | The file [manualCall.js](./manualCall.js) shows you how to make this request using raw JavaScript. 96 | The file [manualCall.py](./manualCall.py) shows you how to make this request using raw Python. -------------------------------------------------------------------------------- /lessons/10-sending-json/manualCall.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | 3 | const apiObject = { 4 | auth: { 5 | username: 'YOUR_SKYCIV_USERNAME', 6 | key: 'YOUR_SKYCIV_API_KEY', 7 | }, 8 | functions: [ 9 | { 10 | function: 'S3D.session.start', 11 | arguments: { 12 | keep_open: false, 13 | }, 14 | }, 15 | ], 16 | }; 17 | 18 | const jsonData = JSON.stringify(apiObject); 19 | 20 | const options = { 21 | host: 'api.skyciv.com', 22 | path: '/v3', 23 | method: 'POST', 24 | headers: { 25 | 'Content-Type': 'application/json', 26 | 'Content-Length': jsonData.length, 27 | }, 28 | }; 29 | 30 | callback = function (response) { 31 | let res = ''; 32 | response.on('data', function (chunk) { 33 | res += chunk; 34 | }); 35 | 36 | response.on('end', function () { 37 | const parsedResults = JSON.parse(res) 38 | console.log(parsedResults); 39 | }); 40 | }; 41 | 42 | const req = http.request(options, callback); 43 | req.write(jsonData); 44 | req.end(); 45 | -------------------------------------------------------------------------------- /lessons/10-sending-json/manualCall.py: -------------------------------------------------------------------------------- 1 | import json 2 | import http.client as httplib 3 | 4 | # Mac users - if you get an error similar to this: 5 | # [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123) 6 | # Go to the Python folder in the application directory and run the file "Install Certificates.command" 7 | 8 | 9 | try: # If anything inside this block fails, the "except" block will run 10 | 11 | # What kind of data we are sending 12 | headers = {'Content-Type': 'application/json'} 13 | 14 | # Create a connection to SkyCiv 15 | conn = httplib.HTTPSConnection('api.skyciv.com', 8085) 16 | 17 | # Prepare the payload 18 | api_object = { 19 | "auth": { 20 | "username": "YOUR_SKYCIV_USERNAME", 21 | "key": "YOUR_SKYCIV_API_KEY" 22 | }, 23 | "functions": [ 24 | { 25 | "function": "S3D.session.start", 26 | "arguments": { 27 | "keep_open": False 28 | } 29 | } 30 | ] 31 | } 32 | 33 | json_string = json.dumps(api_object, separators=(',', ':')) 34 | 35 | conn.request('POST', '/v3', json_string, headers) 36 | raw_res = conn.getresponse() 37 | conn.close() 38 | 39 | res_data = raw_res.read() 40 | parsed_res = json.loads(res_data) 41 | 42 | if (parsed_res["response"]["status"] == 0): 43 | with open('pyOutput.json', 'w') as f: 44 | print(parsed_res, file=f) 45 | 46 | else: 47 | print( 48 | f'\nUnsuccessful solve with message: { parsed_res["response"]["msg"] }') 49 | 50 | except Exception as e: 51 | print(f'\nThe following error occured: {e}') 52 | -------------------------------------------------------------------------------- /lessons/10-sending-json/skycivCall.js: -------------------------------------------------------------------------------- 1 | const skyciv = require('skyciv'); 2 | 3 | const apiObject = { 4 | auth: { 5 | username: 'YOUR_SKYCIV_USERNAME', 6 | key: 'YOUR_SKYCIV_API_KEY', 7 | }, 8 | functions: [ 9 | { 10 | function: 'S3D.session.start', 11 | arguments: { 12 | keep_open: false, 13 | }, 14 | }, 15 | ], 16 | }; 17 | 18 | const callback = function (res) { 19 | console.log(res); 20 | }; 21 | 22 | skyciv.request(apiObject, callback); 23 | -------------------------------------------------------------------------------- /lessons/10-sending-json/skycivCall.py: -------------------------------------------------------------------------------- 1 | import skyciv 2 | 3 | api_object = { 4 | "auth": { 5 | "username": "YOUR_SKYCIV_USERNAME", 6 | "key": "YOUR_SKYCIV_API_KEY" 7 | }, 8 | "functions": [ 9 | { 10 | "function": "S3D.session.start", 11 | "arguments": { 12 | "keep_open": False 13 | } 14 | } 15 | ] 16 | } 17 | 18 | # This next line will print an error as the api_object variable above is incorrect. 19 | results = skyciv.request(api_object) 20 | 21 | with open('pyOutput.json', 'w') as f: 22 | print(results, file=f) 23 | -------------------------------------------------------------------------------- /lessons/11-receiving-json/README.md: -------------------------------------------------------------------------------- 1 | # receiving json 2 | 3 | To extract data from the response, we first need to "parse" the JSON response. The JSON libraries that we previously used have a method to parse this infomation. These methods take the json response and converts it to an object (or dictionary). Note that the terms object and dictionary may be used interchangeably from here. 4 | 5 | #### JavaScript 6 | ```js 7 | const parsedResults = JSON.parse(resData); 8 | ``` 9 | 10 | #### Python 11 | ```py 12 | parsed_res = json.loads(res_data) 13 | ``` 14 | 15 | --- 16 | 17 | Carrying on, we now have the response as an object. 18 | 19 | The following sample is a real response from the SkyCiv API. The call ran a function to start a session and nothing else. We will look further into the SkyCiv input and output objects in upcoming lessons. For now we are just going to grab some values from this response object. 20 | 21 | ```py 22 | parsed_res = { 23 | "response": { 24 | "session_id": "1FOmVIqbBsF0K6vXVrJhcxmyc95p0LCG1PwnDsN2dfXIB3Grby3vxzNiSBEem8zR_0", 25 | "session_expiry_time": 1610337096, 26 | "msg": "S3D session successfully started.", 27 | "status": 0, 28 | "function": "S3D.session.start", 29 | "data": "", 30 | "last_session_id": "1FOmVIqbBsF0K6vXVrJhcxmyc95p0LCG1PwnDsN2dfXIB3Grby3vxzNiSBEem8zR_0" 31 | }, 32 | "functions": [ 33 | { 34 | "session_id": "1FOmVIqbBsF0K6vXVrJhcxmyc95p0LCG1PwnDsN2dfXIB3Grby3vxzNiSBEem8zR_0", 35 | "session_expiry_time": 1610337096, 36 | "msg": "S3D session successfully started.", 37 | "status": 0, 38 | "function": "S3D.session.start", 39 | "data": "" 40 | } 41 | ] 42 | } 43 | ``` 44 | 45 | The first thing worth noting is that the dictionary contains two keys, `"response"` and `"functions"`. The value of `"response"` is an object while the value of `"functions"` is an array. 46 | 47 | --- 48 | 49 | ### Accessing objects 50 | 51 | Say we want to get the value of `"msg"` from the `"response"` object. In Python, we can do so like this: 52 | 53 | ```py 54 | message = parsed_res["response"]["msg"] 55 | ``` 56 | 57 | However, if this key doesn't exist, we will get an error. Instead, we can check if the key exists and print it if so. 58 | 59 | ```py 60 | if "msg" in parsed_res["response"]: 61 | message = parsed_res["response"]["msg"] 62 | print(message) 63 | ``` 64 | 65 | Similarly in JavaScript: 66 | 67 | ```js 68 | const responseKeys = Object.keys(parsedResults["response"]); // Gets an array of keys 69 | if (responseKeys.includes("msg")) { 70 | const message = parsedResults["response"]["msg"]; 71 | console.log(message); 72 | } 73 | ``` 74 | 75 | In JavaScript you can also drill down an object by chaining keys: 76 | 77 | ```js 78 | const message = parsedResults.response.msg; 79 | ``` 80 | 81 | However, to insert variable keys you will need to use the former method. 82 | 83 | --- 84 | 85 | ### Accessing arrays 86 | 87 | Now looking at the `"functions"` array. This is an array of objects - in our case, one object. Let's get the value of the status key. 88 | 89 | We know that arrays start from an index of 0, so we can get the first object in the array like so: 90 | 91 | ```py 92 | first_func = parsed_res["functions"][0] 93 | status = first_func["status"] 94 | ``` 95 | 96 | and in one line using JavaScript: 97 | 98 | ```js 99 | const status = parsedResults.functions[0].status 100 | ``` 101 | 102 | Note using the chain syntax for an array index is not valid, for example `parsedResults.functions.0.status` will not work. 103 | 104 | Have a look at the following files for a full example of starting a session. 105 | 106 | * [Python](./index.py) 107 | * [JavaScript](./index.js) 108 | -------------------------------------------------------------------------------- /lessons/11-receiving-json/index.js: -------------------------------------------------------------------------------- 1 | const skyciv = require('skyciv'); 2 | 3 | const apiObject = { 4 | auth: { "username": "YOUR_SKYCIV_USERNAME", "key": "OUR_SKYCIV_API_KEY" }, 5 | functions: [ 6 | { 7 | function: 'S3D.session.start', 8 | arguments: { 9 | keep_open: false, 10 | } 11 | } 12 | ] 13 | }; 14 | 15 | const callback = function (res) { 16 | const responseKeys = Object.keys(res['response']); 17 | if (responseKeys.includes('msg')) { 18 | console.log( 19 | `Successful request with the following response message from SkyCiv: ${res.response.msg}` 20 | ); 21 | } 22 | }; 23 | 24 | skyciv.request(apiObject, callback); 25 | -------------------------------------------------------------------------------- /lessons/11-receiving-json/index.py: -------------------------------------------------------------------------------- 1 | import skyciv 2 | 3 | api_object = { 4 | "auth": { 5 | username: 'YOUR_SKYCIV_USERNAME', 6 | key: 'YOUR_SKYCIV_API_KEY', 7 | }, 8 | "functions": [ 9 | { 10 | "function": "S3D.session.start", 11 | "arguments": { 12 | "keep_open": False 13 | } 14 | } 15 | ] 16 | } 17 | 18 | # This next line will print an error as the data variable above is incorrect. 19 | results = skyciv.request(api_object, {}) 20 | 21 | response = results["response"] 22 | 23 | if "msg" in response: 24 | print( 25 | f'Successful request with the following response message from SkyCiv: {response["msg"]}') 26 | -------------------------------------------------------------------------------- /lessons/12-skyciv-api-object/README.md: -------------------------------------------------------------------------------- 1 | # skyciv api object 2 | 3 | This lesson will teach you how to use the [SkyCiv API docs](https://skyciv.com/api/v3/docs) to create a request object. 4 | 5 | The input object that you must supply in the request is comprised of three components. 6 | 7 | 1. The `auth` object which is required. 8 | 2. The `options` object which is optional. 9 | 3. The `functions` array which must contain at least one item. 10 | 11 | Check out what values can be assigned to these keys [here](https://skyciv.com/api/v3/docs/the-request-object). -------------------------------------------------------------------------------- /lessons/13-auth-and-options/README.md: -------------------------------------------------------------------------------- 1 | # auth and options 2 | 3 | In this lesson we look at creating the [`auth`](https://skyciv.com/api/v3/docs/the-request-object#auth) and [`options`](https://skyciv.com/api/v3/docs/the-request-object#options) objects by following the documentation. 4 | 5 | We'll then start to compile our API object which we will add to in the next couple of videos. -------------------------------------------------------------------------------- /lessons/13-auth-and-options/index.js: -------------------------------------------------------------------------------- 1 | // Create auth object 2 | const auth = { 3 | username: 'YOUR_SKYCIV_USERNAME', 4 | key: 'YOUR_SKYCIV_API_KEY', 5 | }; 6 | 7 | // Create options object - this is the default values so you could instead omit the entire object 8 | const options = { 9 | validate_input: true, 10 | response_data_only: false, 11 | }; 12 | 13 | // Create the api object and add auth and options 14 | const apiObject = { 15 | auth: auth, 16 | options: options, 17 | }; 18 | -------------------------------------------------------------------------------- /lessons/13-auth-and-options/index.py: -------------------------------------------------------------------------------- 1 | # Create auth object 2 | auth = { 3 | "username": "YOUR_SKYCIV_USERNAME", 4 | "key": "YOUR_SKYCIV_API_KEY" 5 | } 6 | 7 | # Create options object - this is the default values so you could instead omit the entire object 8 | options = { 9 | "validate_input": True, 10 | "response_data_only": False 11 | } 12 | 13 | # Create the api object and add auth and options 14 | api_object = { 15 | "auth": auth, 16 | "options": options 17 | } 18 | 19 | -------------------------------------------------------------------------------- /lessons/14-s3d-model/README.md: -------------------------------------------------------------------------------- 1 | # s3d model 2 | 3 | In this lesson we will be looking at what we typically refer to as the `s3d_model`. 4 | 5 | Every model that is built with SkyCiv, is stored as JSON. This makes it very easy to read, work with and integrate across platforms. 6 | 7 | The `s3d_model` is a JSON definition that describes every attribute of the Structural 3D model. To prove this, open up any model in [S3D](https://platform.skyciv.com/structural) and click `File > Export > SkyCiv File (JSON for API) > v3`. Open the downloaded file in the code editor and have a look around! Tip: Firefox displays JSON files in a very readable format. 8 | 9 | This may serve as a guide to create your own s3d_model. It's also a great way to create a template. 10 | 11 | --- 12 | 13 | ### Components 14 | 15 | The following properties are the core pieces to creating the `s3d_model`. Detailed information on each of them can be found on the [`s3d_model` page](https://skyciv.com/api/v3/docs/s3d-model#s3d_model) of the docs. 16 | 17 | * `settings` 18 | * `nodes` 19 | * `members` 20 | * `plates` 21 | * `meshed_plates` 22 | * `sections` 23 | * `materials` 24 | * `supports` 25 | * `settlements` 26 | * `point_loads` 27 | * `moments` 28 | * `distributed_loads` 29 | * `pressures` 30 | * `area_loads` 31 | * `self_weight` 32 | * `load_combinations` 33 | 34 | The `settings` property contains all the general setup information of the model whilst every other explicitly defines components of the model such as nodes, members, loads. -------------------------------------------------------------------------------- /lessons/14-s3d-model/index.js: -------------------------------------------------------------------------------- 1 | // ========== FROM PREVIOUS LESSON ============================================================== 2 | // Create auth object 3 | const auth = { 4 | username: 'YOUR_SKYCIV_USERNAME', 5 | key: 'YOUR_SKYCIV_API_KEY', 6 | }; 7 | 8 | // Create options object - this is the default values so you could instead omit the entire object 9 | const options = { 10 | validate_input: true, 11 | response_data_only: false, 12 | }; 13 | 14 | // Create the api object and add auth and options 15 | const apiObject = { 16 | auth: auth, 17 | options: options, 18 | }; 19 | // ========== THIS LESSON ======================================================================= 20 | 21 | // Creating the s3d_model 22 | const s3d_model = { 23 | settings: { 24 | units: 'metric', 25 | vertical_axis: 'Y', 26 | evaluation_points: 15, 27 | }, 28 | nodes: { 29 | 1: { 30 | x: 0, 31 | y: 0, 32 | z: 0, 33 | }, 34 | 2: { 35 | x: 5, 36 | y: 0, 37 | z: 0, 38 | }, 39 | }, 40 | members: { 41 | 1: { 42 | node_A: 1, 43 | node_B: 2, 44 | section_id: 1, 45 | fixity_A: 'FFFfff', 46 | fixity_B: 'FFFfff', 47 | }, 48 | }, 49 | sections: { 50 | 1: { 51 | load_section: ['Australian', 'Steel (300 Grade)', 'Universal beams', '150 UB 18.0'], 52 | material_id: 1, 53 | }, 54 | }, 55 | materials: { 56 | 1: { 57 | id: 1, 58 | name: 'Structural Steel', 59 | density: 7850, 60 | elasticity_modulus: 200000, 61 | poissons_ratio: 0.27, 62 | yield_strength: 260, 63 | ultimate_strength: 410, 64 | class: 'steel', 65 | }, 66 | }, 67 | supports: { 68 | 1: { 69 | node: 1, 70 | restraint_code: 'FFFfff', 71 | }, 72 | 2: { 73 | node: 2, 74 | restraint_code: 'RFFffr', 75 | }, 76 | }, 77 | point_loads: { 78 | 1: { 79 | type: 'm', 80 | member: 1, 81 | position: 30, 82 | x_mag: 0, 83 | y_mag: -10, 84 | z_mag: 0, 85 | load_group: 'LG1', 86 | }, 87 | }, 88 | }; 89 | -------------------------------------------------------------------------------- /lessons/14-s3d-model/index.py: -------------------------------------------------------------------------------- 1 | # ========== FROM PREVIOUS LESSON ============================================================== 2 | # Create auth object 3 | auth = { 4 | "username": "YOUR_SKYCIV_USERNAME", 5 | "key": "YOUR_SKYCIV_API_KEY" 6 | } 7 | 8 | # Create options object - this is the default values so you could instead omit the entire object 9 | options = { 10 | "validate_input": True, 11 | "response_data_only": False 12 | } 13 | 14 | # Create the api object and add auth and options 15 | api_object = { 16 | "auth": auth, 17 | "options": options 18 | } 19 | 20 | # ========== THIS LESSON ======================================================================= 21 | 22 | # Creating the s3d_model 23 | 24 | s3d_model = { 25 | "settings": { 26 | "units": "metric", 27 | "vertical_axis": "Y", 28 | "evaluation_points": 15 29 | }, 30 | "nodes": { 31 | "1": { 32 | "x": 0, 33 | "y": 0, 34 | "z": 0, 35 | }, 36 | "2": { 37 | "x": 5, 38 | "y": 0, 39 | "z": 0, 40 | }, 41 | }, 42 | "members": { 43 | "1": { 44 | "node_A": 1, 45 | "node_B": 2, 46 | "section_id": 1, 47 | "fixity_A": "FFFfff", 48 | "fixity_B": "FFFfff", 49 | }, 50 | }, 51 | "sections": { 52 | "1": { 53 | "load_section": ["Australian", "Steel (300 Grade)", "Universal beams", "150 UB 18.0"], 54 | "material_id": 1 55 | } 56 | }, 57 | "materials": { 58 | "1": { 59 | "name": "Structural Steel", 60 | "density": 7850, 61 | "elasticity_modulus": 200000, 62 | "poissons_ratio": 0.27, 63 | "yield_strength": 260, 64 | "ultimate_strength": 410, 65 | "class": "steel", 66 | }, 67 | }, 68 | "supports": { 69 | "1": { 70 | "node": 1, 71 | "restraint_code": "FFFfff", 72 | }, 73 | "2": { 74 | "node": 2, 75 | "restraint_code": "RFFffr", 76 | }, 77 | }, 78 | "point_loads": { 79 | "1": { 80 | "type": "m", 81 | "member": 1, 82 | "position": 30, 83 | "x_mag": 0, 84 | "y_mag": -10, 85 | "z_mag": 0, 86 | "load_group": "LG1" 87 | }, 88 | }, 89 | } 90 | -------------------------------------------------------------------------------- /lessons/15-functions/README.md: -------------------------------------------------------------------------------- 1 | # functions 2 | 3 | The SkyCiv API object takes an array of functions. The order which you provide these functions is the order they will be executed. Find a list of avaialable functions in [the docs](https://skyciv.com/api/v3/docs/the-request-object#functions). 4 | 5 | When you send a request to the SkyCiv API, think of it exactly how you would achieve this if you were to use the browser. 6 | 7 | A smaller workflow might look something like this: 8 | 1. First you need to **"start a session"** with skyciv.com which you do by opening the webpage and signing in. 9 | 2. Open Structural 3D and **"set your model"** by adding nodes, members etc. 10 | 3. Click the **"solve"** button to instruct the SkyCiv server to perform FEA on the model and give you results. 11 | 4. Click the **"design"** button to instruct the SkyCiv server to run a design on your model. 12 | 5. **"Save"** the model to our SkyCiv account. 13 | 14 | Well, this is essentially what the `functions` property is for! We need to choose the set of instructions which suits our need. 15 | 16 | Using the above workflow the functions array might look like this: 17 | ```py 18 | { 19 | auth: {}, 20 | options: {}, 21 | functions: [ 22 | { 23 | "function": "S3D.session.start", 24 | "arguments" : { 25 | "keep_open": False # Don't forget, Python syntax! 26 | } 27 | }, 28 | { 29 | "function": "S3D.model.set", 30 | "arguments": { 31 | "s3d_model": s3d_model 32 | } 33 | }, 34 | { 35 | "function": "S3D.model.solve", 36 | "arguments": { 37 | "analysis_type": "linear", 38 | } 39 | }, 40 | { 41 | "function": "S3D.design.member.check", 42 | "arguments": { 43 | "design_code": "AS_4100-1998", 44 | "s3d_model": s3d_model, 45 | } 46 | }, 47 | { 48 | "function": "S3D.file.save", 49 | "arguments": { 50 | "name": "simple-beam-test", 51 | "path": "api/intro-to-programming/" 52 | } 53 | } 54 | ] 55 | } 56 | ``` -------------------------------------------------------------------------------- /lessons/15-functions/index.js: -------------------------------------------------------------------------------- 1 | // ========== FROM PREVIOUS LESSON ============================================================== 2 | // Create auth object 3 | const auth = { 4 | username: 'YOUR_SKYCIV_USERNAME', 5 | key: 'YOUR_SKYCIV_API_KEY', 6 | }; 7 | 8 | // Create options object - this is the default values so you could instead omit the entire object 9 | const options = { 10 | validate_input: true, 11 | response_data_only: false, 12 | }; 13 | 14 | // Create the api object and add auth and options 15 | const apiObject = { 16 | auth: auth, 17 | options: options, 18 | }; 19 | 20 | // Creating the s3d_model 21 | const s3dModel = { 22 | settings: { 23 | units: 'metric', 24 | vertical_axis: 'Y', 25 | evaluation_points: 15, 26 | }, 27 | nodes: { 28 | 1: { 29 | x: 0, 30 | y: 0, 31 | z: 0, 32 | }, 33 | 2: { 34 | x: 5, 35 | y: 0, 36 | z: 0, 37 | }, 38 | }, 39 | members: { 40 | 1: { 41 | node_A: 1, 42 | node_B: 2, 43 | section_id: 1, 44 | fixity_A: 'FFFfff', 45 | fixity_B: 'FFFfff', 46 | }, 47 | }, 48 | sections: { 49 | 1: { 50 | load_section: ['Australian', 'Steel (300 Grade)', 'Universal beams', '150 UB 18.0'], 51 | material_id: 1, 52 | }, 53 | }, 54 | materials: { 55 | 1: { 56 | id: 1, 57 | name: 'Structural Steel', 58 | density: 7850, 59 | elasticity_modulus: 200000, 60 | poissons_ratio: 0.27, 61 | yield_strength: 260, 62 | ultimate_strength: 410, 63 | class: 'steel', 64 | }, 65 | }, 66 | supports: { 67 | 1: { 68 | node: 1, 69 | restraint_code: 'FFFfff', 70 | }, 71 | 2: { 72 | node: 2, 73 | restraint_code: 'RFFffr', 74 | }, 75 | }, 76 | point_loads: { 77 | 1: { 78 | type: 'm', 79 | member: 1, 80 | position: 30, 81 | x_mag: 0, 82 | y_mag: -10, 83 | z_mag: 0, 84 | load_group: 'LG1', 85 | }, 86 | }, 87 | }; 88 | 89 | // ========== THIS LESSON ======================================================================= 90 | 91 | // Creating the functions array 92 | const functions = [ 93 | { 94 | function: 'S3D.session.start', 95 | arguments: { 96 | keep_open: false, 97 | }, 98 | }, 99 | { 100 | function: 'S3D.model.set', 101 | arguments: { 102 | s3d_model: s3dModel, 103 | }, 104 | }, 105 | { 106 | function: 'S3D.model.solve', 107 | arguments: { 108 | analysis_type: 'linear', 109 | }, 110 | }, 111 | { 112 | function: 'S3D.design.member.check', 113 | arguments: { 114 | design_code: 'AS_4100-1998', 115 | s3d_model: s3dModel, 116 | }, 117 | }, 118 | { 119 | function: 'S3D.file.save', 120 | arguments: { 121 | name: 'simple-beam-test', 122 | path: 'api/intro-to-programming/', 123 | }, 124 | }, 125 | ]; 126 | 127 | // Adding the functions array to the api object 128 | apiObject['functions'] = functions; 129 | -------------------------------------------------------------------------------- /lessons/15-functions/index.py: -------------------------------------------------------------------------------- 1 | # ========== FROM PREVIOUS LESSON ============================================================== 2 | # Create auth object 3 | auth = { 4 | "username": "YOUR_SKYCIV_USERNAME", 5 | "key": "YOUR_SKYCIV_API_KEY" 6 | } 7 | 8 | # Create options object - this is the default values so you could instead omit the entire object 9 | options = { 10 | "validate_input": True, 11 | "response_data_only": False 12 | } 13 | 14 | # Create the api object and add auth and options 15 | api_object = { 16 | "auth": auth, 17 | "options": options 18 | } 19 | 20 | # Creating the s3d_model 21 | s3d_model = { 22 | "settings": { 23 | "units": "metric", 24 | "vertical_axis": "Y", 25 | "evaluation_points": 15 26 | }, 27 | "nodes": { 28 | "1": { 29 | "x": 0, 30 | "y": 0, 31 | "z": 0, 32 | }, 33 | "2": { 34 | "x": 5, 35 | "y": 0, 36 | "z": 0, 37 | }, 38 | }, 39 | "members": { 40 | "1": { 41 | "node_A": 1, 42 | "node_B": 2, 43 | "section_id": 1, 44 | "fixity_A": "FFFfff", 45 | "fixity_B": "FFFfff", 46 | }, 47 | }, 48 | "sections": { 49 | "1": { 50 | "load_section": ["Australian", "Steel (300 Grade)", "Universal beams", "150 UB 18.0"], 51 | "material_id": 1 52 | } 53 | }, 54 | "materials": { 55 | "1": { 56 | "name": "Structural Steel", 57 | "density": 7850, 58 | "elasticity_modulus": 200000, 59 | "poissons_ratio": 0.27, 60 | "yield_strength": 260, 61 | "ultimate_strength": 410, 62 | "class": "steel", 63 | }, 64 | }, 65 | "supports": { 66 | "1": { 67 | "node": 1, 68 | "restraint_code": "FFFfff", 69 | }, 70 | "2": { 71 | "node": 2, 72 | "restraint_code": "RFFffr", 73 | }, 74 | }, 75 | "point_loads": { 76 | "1": { 77 | "type": "m", 78 | "member": 1, 79 | "position": 30, 80 | "x_mag": 0, 81 | "y_mag": -10, 82 | "z_mag": 0, 83 | "load_group": "LG1" 84 | }, 85 | }, 86 | } 87 | 88 | # ========== THIS LESSON ======================================================================= 89 | 90 | # Creating the functions array 91 | functions = [ 92 | { 93 | "function": "S3D.session.start", 94 | "arguments": { 95 | "keep_open": False 96 | } 97 | }, 98 | { 99 | "function": "S3D.model.set", 100 | "arguments": { 101 | "s3d_model": s3d_model 102 | } 103 | }, 104 | { 105 | "function": "S3D.model.solve", 106 | "arguments": { 107 | "analysis_type": "linear", 108 | } 109 | }, 110 | { 111 | "function": "S3D.design.member.check", 112 | "arguments": { 113 | "design_code": "AS_4100-1998", 114 | "s3d_model": s3d_model, 115 | } 116 | }, 117 | { 118 | "function": "S3D.file.save", 119 | "arguments": { 120 | "name": "simple-beam-test", 121 | "path": "api/intro-to-programming/" 122 | } 123 | } 124 | ] 125 | 126 | # Adding the functions array to the api object 127 | api_object["functions"] = functions 128 | -------------------------------------------------------------------------------- /lessons/16-making-the-http-request/README.md: -------------------------------------------------------------------------------- 1 | # making the http request 2 | 3 | Now we've created the API object, we can send it to the SkyCiv servers just like we did earlier! 4 | 5 | * [Python](./index.py) 6 | * [JavaScript](./index.js) -------------------------------------------------------------------------------- /lessons/16-making-the-http-request/index.js: -------------------------------------------------------------------------------- 1 | const skyciv = require('skyciv'); 2 | const fs = require('fs'); 3 | 4 | // ========== FROM PREVIOUS LESSON ============================================================== 5 | // Create auth object 6 | const auth = { 7 | username: 'YOUR_SKYCIV_USERNAME', 8 | key: 'YOUR_SKYCIV_API_KEY', 9 | }; 10 | 11 | // Create options object - this is the default values so you could instead omit the entire object 12 | const options = { 13 | validate_input: true, 14 | response_data_only: false, 15 | }; 16 | 17 | // Create the api object and add auth and options 18 | const apiObject = { 19 | auth: auth, 20 | options: options, 21 | }; 22 | 23 | // Creating the s3d_model 24 | const s3dModel = { 25 | settings: { 26 | units: 'metric', 27 | vertical_axis: 'Y', 28 | evaluation_points: 15, 29 | }, 30 | nodes: { 31 | 1: { 32 | x: 0, 33 | y: 0, 34 | z: 0, 35 | }, 36 | 2: { 37 | x: 5, 38 | y: 0, 39 | z: 0, 40 | }, 41 | }, 42 | members: { 43 | 1: { 44 | node_A: 1, 45 | node_B: 2, 46 | section_id: 1, 47 | fixity_A: 'FFFfff', 48 | fixity_B: 'FFFfff', 49 | }, 50 | }, 51 | sections: { 52 | 1: { 53 | load_section: ['Australian', 'Steel (300 Grade)', 'Universal beams', '150 UB 18.0'], 54 | material_id: 1, 55 | }, 56 | }, 57 | materials: { 58 | 1: { 59 | id: 1, 60 | name: 'Structural Steel', 61 | density: 7850, 62 | elasticity_modulus: 200000, 63 | poissons_ratio: 0.27, 64 | yield_strength: 260, 65 | ultimate_strength: 410, 66 | class: 'steel', 67 | }, 68 | }, 69 | supports: { 70 | 1: { 71 | node: 1, 72 | restraint_code: 'FFFfff', 73 | }, 74 | 2: { 75 | node: 2, 76 | restraint_code: 'RFFffr', 77 | }, 78 | }, 79 | point_loads: { 80 | 1: { 81 | type: 'm', 82 | member: 1, 83 | position: 30, 84 | x_mag: 0, 85 | y_mag: -10, 86 | z_mag: 0, 87 | load_group: 'LG1', 88 | }, 89 | }, 90 | }; 91 | 92 | // Creating the functions array 93 | const functions = [ 94 | { 95 | function: 'S3D.session.start', 96 | arguments: { 97 | keep_open: false, 98 | }, 99 | }, 100 | { 101 | function: 'S3D.model.set', 102 | arguments: { 103 | s3d_model: s3dModel, 104 | }, 105 | }, 106 | { 107 | function: 'S3D.model.solve', 108 | arguments: { 109 | analysis_type: 'linear', 110 | }, 111 | }, 112 | { 113 | function: 'S3D.design.member.check', 114 | arguments: { 115 | design_code: 'AS_4100-1998', 116 | s3d_model: s3dModel, 117 | }, 118 | }, 119 | { 120 | function: 'S3D.file.save', 121 | arguments: { 122 | name: 'simple-beam-test', 123 | path: 'api/intro-to-programming/', 124 | }, 125 | }, 126 | ]; 127 | 128 | // Adding the functions array to the api object 129 | apiObject['functions'] = functions; 130 | 131 | // ========== THIS LESSON ======================================================================= 132 | 133 | // Import the skyciv package at the top of this script 134 | 135 | // Create a function to handle the response 136 | function apiCallback(res) { 137 | // Add the response to a file for inspection 138 | // Import the fs module at the top of the file 139 | fs.writeFileSync('jsOutput.json', JSON.stringify(res)); 140 | 141 | // NEXT LESSON 142 | console.log(res.response.status); 143 | } 144 | 145 | // Make the call! 146 | skyciv.request(apiObject, apiCallback); 147 | -------------------------------------------------------------------------------- /lessons/16-making-the-http-request/index.py: -------------------------------------------------------------------------------- 1 | import skyciv 2 | 3 | # ========== FROM PREVIOUS LESSON ============================================================== 4 | # Create auth object 5 | auth = { 6 | username: 'YOUR_SKYCIV_USERNAME', 7 | key: 'YOUR_SKYCIV_API_KEY', 8 | } 9 | 10 | # Create options object - this is the default values so you could instead omit the entire object 11 | options = { 12 | "validate_input": True, 13 | "response_data_only": False 14 | } 15 | 16 | # Create the api object and add auth and options 17 | api_object = { 18 | "auth": auth, 19 | "options": options 20 | } 21 | 22 | # Creating the s3d_model 23 | s3d_model = { 24 | "settings": { 25 | "units": "metric", 26 | "vertical_axis": "Y", 27 | "evaluation_points": 15 28 | }, 29 | "nodes": { 30 | "1": { 31 | "x": 0, 32 | "y": 0, 33 | "z": 0, 34 | }, 35 | "2": { 36 | "x": 5, 37 | "y": 0, 38 | "z": 0, 39 | }, 40 | }, 41 | "members": { 42 | "1": { 43 | "node_A": 1, 44 | "node_B": 2, 45 | "section_id": 1, 46 | "fixity_A": "FFFfff", 47 | "fixity_B": "FFFfff", 48 | }, 49 | }, 50 | "sections": { 51 | "1": { 52 | "load_section": ["Australian", "Steel (300 Grade)", "Universal beams", "150 UB 18.0"], 53 | "material_id": 1 54 | } 55 | }, 56 | "materials": { 57 | "1": { 58 | "name": "Structural Steel", 59 | "density": 7850, 60 | "elasticity_modulus": 200000, 61 | "poissons_ratio": 0.27, 62 | "yield_strength": 260, 63 | "ultimate_strength": 410, 64 | "class": "steel", 65 | }, 66 | }, 67 | "supports": { 68 | "1": { 69 | "node": 1, 70 | "restraint_code": "FFFfff", 71 | }, 72 | "2": { 73 | "node": 2, 74 | "restraint_code": "RFFffr", 75 | }, 76 | }, 77 | "point_loads": { 78 | "1": { 79 | "type": "m", 80 | "member": 1, 81 | "position": 30, 82 | "x_mag": 0, 83 | "y_mag": -10, 84 | "z_mag": 0, 85 | "load_group": "LG1" 86 | }, 87 | }, 88 | } 89 | 90 | # Creating the functions array 91 | functions = [ 92 | { 93 | "function": "S3D.session.start", 94 | "arguments": { 95 | "keep_open": False 96 | } 97 | }, 98 | { 99 | "function": "S3D.model.set", 100 | "arguments": { 101 | "s3d_model": s3d_model 102 | } 103 | }, 104 | { 105 | "function": "S3D.model.solve", 106 | "arguments": { 107 | "analysis_type": "linear", 108 | } 109 | }, 110 | { 111 | "function": "S3D.design.member.check", 112 | "arguments": { 113 | "design_code": "AS_4100-1998", 114 | "s3d_model": s3d_model, 115 | } 116 | }, 117 | { 118 | "function": "S3D.file.save", 119 | "arguments": { 120 | "name": "simple-beam-test", 121 | "path": "api/intro-to-programming/" 122 | } 123 | } 124 | ] 125 | 126 | # Adding the functions array to the api object 127 | api_object["functions"] = functions 128 | 129 | # ========== THIS LESSON ======================================================================= 130 | 131 | # Import the skyciv package at the top of this script 132 | 133 | # Make the call! 134 | res = skyciv.request(api_object, {}) 135 | 136 | # Add the response to a file for inspection 137 | with open("pyOutput.json", "w") as f: 138 | print(res, file=f) 139 | -------------------------------------------------------------------------------- /lessons/17-interpreting-the-response/README.md: -------------------------------------------------------------------------------- 1 | # interpreting the response 2 | 3 | We've done it! We now have a real response which has performed a bunch of useful functions. 4 | 5 | Let's dig through the response. 6 | 7 | --- 8 | 9 | ### Breaking down the response 10 | 11 | The first thing to understand is what the `response` and `functions` properties contain. 12 | 13 | **The `response` key contains the same information as the `data` key of the last function in the functions array.** 14 | 15 | The `functions` array contains an array of function responses. These are in the same order that was specified in the input object. 16 | 17 | You can explore the output of our API object in one of the following files: 18 | * [jsOutput.json](./jsOutput.json) 19 | * [pyOutput.json](./pyOutput.json) 20 | 21 | Like we did previously, we can loop the response objects and drill down into them to read certain values. So let's get the peak displacement in the Y and stresses about Z: 22 | * [index.js](./index.js) 23 | * [index.py](./index.py) -------------------------------------------------------------------------------- /lessons/17-interpreting-the-response/index.js: -------------------------------------------------------------------------------- 1 | const skyciv = require('skyciv'); 2 | const fs = require('fs'); 3 | 4 | // ========== FROM PREVIOUS LESSON ============================================================== 5 | // Create auth object 6 | const auth = { 7 | username: 'YOUR_SKYCIV_USERNAME', 8 | key: 'YOUR_SKYCIV_API_KEY', 9 | }; 10 | 11 | // Create options object - this is the default values so you could instead omit the entire object 12 | const options = { 13 | validate_input: true, 14 | response_data_only: false, 15 | }; 16 | 17 | // Create the api object and add auth and options 18 | const apiObject = { 19 | auth: auth, 20 | options: options, 21 | }; 22 | 23 | // Creating the s3d_model 24 | const s3dModel = { 25 | settings: { 26 | units: 'metric', 27 | vertical_axis: 'Y', 28 | evaluation_points: 15, 29 | }, 30 | nodes: { 31 | 1: { 32 | x: 0, 33 | y: 0, 34 | z: 0, 35 | }, 36 | 2: { 37 | x: 5, 38 | y: 0, 39 | z: 0, 40 | }, 41 | }, 42 | members: { 43 | 1: { 44 | node_A: 1, 45 | node_B: 2, 46 | section_id: 1, 47 | fixity_A: 'FFFfff', 48 | fixity_B: 'FFFfff', 49 | }, 50 | }, 51 | sections: { 52 | 1: { 53 | load_section: ['Australian', 'Steel (300 Grade)', 'Universal beams', '150 UB 18.0'], 54 | material_id: 1, 55 | }, 56 | }, 57 | materials: { 58 | 1: { 59 | id: 1, 60 | name: 'Structural Steel', 61 | density: 7850, 62 | elasticity_modulus: 200000, 63 | poissons_ratio: 0.27, 64 | yield_strength: 260, 65 | ultimate_strength: 410, 66 | class: 'steel', 67 | }, 68 | }, 69 | supports: { 70 | 1: { 71 | node: 1, 72 | restraint_code: 'FFFfff', 73 | }, 74 | 2: { 75 | node: 2, 76 | restraint_code: 'RFFffr', 77 | }, 78 | }, 79 | point_loads: { 80 | 1: { 81 | type: 'm', 82 | member: 1, 83 | position: 30, 84 | x_mag: 0, 85 | y_mag: -10, 86 | z_mag: 0, 87 | load_group: 'LG1', 88 | }, 89 | }, 90 | }; 91 | 92 | // Creating the functions array 93 | const functions = [ 94 | { 95 | function: 'S3D.session.start', 96 | arguments: { 97 | keep_open: false, 98 | }, 99 | }, 100 | { 101 | function: 'S3D.model.set', 102 | arguments: { 103 | s3d_model: s3dModel, 104 | }, 105 | }, 106 | { 107 | function: 'S3D.model.solve', 108 | arguments: { 109 | analysis_type: 'linear', 110 | }, 111 | }, 112 | { 113 | function: 'S3D.design.member.check', 114 | arguments: { 115 | design_code: 'AS_4100-1998', 116 | s3d_model: s3dModel, 117 | }, 118 | }, 119 | { 120 | function: 'S3D.file.save', 121 | arguments: { 122 | name: 'simple-beam-test', 123 | path: 'api/intro-to-programming/', 124 | }, 125 | }, 126 | ]; 127 | 128 | // Adding the functions array to the api object 129 | apiObject['functions'] = functions; 130 | 131 | // Import the skyciv package at the top of this script 132 | 133 | // Create a function to handle the response 134 | function apiCallback(res) { 135 | // Add the response to a file for inspection 136 | // Import the fs module at the top of the file 137 | fs.writeFileSync('lessons/17-interpreting-the-response/jsOutput.json', JSON.stringify(res)); 138 | 139 | // ========== THIS LESSON ======================================================================= 140 | 141 | // FYI: Traditional way to loop - "in" will loop array index (0,1,2,3,4) and of will loop the values (each object in the array) 142 | for (fn of res.functions) { 143 | if (fn.function === 'S3D.model.solve') { 144 | // Do something with the function results 145 | } 146 | } 147 | 148 | // Modern way to loop an array - use the array method forEach. 149 | res.functions.forEach((fn) => { 150 | // Check if fn is the solve function 151 | if (fn.function === 'S3D.model.solve') { 152 | // Do something with the function results 153 | const loadGroup1 = fn.data['0']; 154 | 155 | // Get peak displacements 156 | const peakResults = loadGroup1.member_peak_results; 157 | const peakDispMinY = peakResults.displacement_local_y.min; 158 | const peakDispMaxY = peakResults.displacement_local_y.max; 159 | 160 | // Get max stress 161 | const memberMaximums = loadGroup1.member_maximums; 162 | const topCombinedStressZ = memberMaximums.top_combined_stress_z['1']; 163 | const btmCombinedStressZ = memberMaximums.btm_combined_stress_z['1']; 164 | 165 | // Check deflection criteria 166 | const allowableDisp = 5000 / 300; // ~16.67 167 | const maxDispPass = Math.abs(peakDispMaxY) < allowableDisp; 168 | const minDispPass = Math.abs(peakDispMinY) < allowableDisp; 169 | 170 | if (maxDispPass && minDispPass) { 171 | console.log('Displacement is ok! 🥳'); 172 | } else { 173 | console.log('Displacement criteria failed 😔'); 174 | } 175 | 176 | // Check stress criteria 177 | const allowableStress = 270; // Say 270MPa 178 | const topStressPass = Math.abs(topCombinedStressZ) < allowableStress; 179 | const btmStressPass = Math.abs(btmCombinedStressZ) < allowableStress; 180 | 181 | if (topStressPass && btmStressPass) { 182 | console.log('Stress criteria passed! 🎉'); 183 | } else { 184 | console.log('Stress criteria failed! 😥'); 185 | } 186 | } 187 | }); 188 | } 189 | 190 | // Make the call! 191 | skyciv.request(apiObject, apiCallback); 192 | -------------------------------------------------------------------------------- /lessons/17-interpreting-the-response/index.py: -------------------------------------------------------------------------------- 1 | import skyciv 2 | 3 | # ========== FROM PREVIOUS LESSON ============================================================== 4 | # Create auth object 5 | auth = { 6 | username: 'YOUR_SKYCIV_USERNAME', 7 | key: 'YOUR_SKYCIV_API_KEY', 8 | } 9 | 10 | # Create options object - this is the default values so you could instead omit the entire object 11 | options = { 12 | "validate_input": True, 13 | "response_data_only": False 14 | } 15 | 16 | # Create the api object and add auth and options 17 | api_object = { 18 | "auth": auth, 19 | "options": options 20 | } 21 | 22 | # Creating the s3d_model 23 | s3d_model = { 24 | "settings": { 25 | "units": "metric", 26 | "vertical_axis": "Y", 27 | "evaluation_points": 15 28 | }, 29 | "nodes": { 30 | "1": { 31 | "x": 0, 32 | "y": 0, 33 | "z": 0, 34 | }, 35 | "2": { 36 | "x": 5, 37 | "y": 0, 38 | "z": 0, 39 | }, 40 | }, 41 | "members": { 42 | "1": { 43 | "node_A": 1, 44 | "node_B": 2, 45 | "section_id": 1, 46 | "fixity_A": "FFFfff", 47 | "fixity_B": "FFFffr", 48 | }, 49 | }, 50 | "sections": { 51 | "1": { 52 | "load_section": ["Australian", "Steel (300 Grade)", "Universal beams", "150 UB 18.0"], 53 | "material_id": 1 54 | } 55 | }, 56 | "materials": { 57 | "1": { 58 | "name": "Structural Steel", 59 | "density": 7850, 60 | "elasticity_modulus": 200000, 61 | "poissons_ratio": 0.27, 62 | "yield_strength": 260, 63 | "ultimate_strength": 410, 64 | "class": "steel", 65 | }, 66 | }, 67 | "supports": { 68 | "1": { 69 | "node": 1, 70 | "restraint_code": "FFFfff", 71 | }, 72 | "2": { 73 | "node": 2, 74 | "restraint_code": "RFFffr", 75 | }, 76 | }, 77 | "point_loads": { 78 | "1": { 79 | "type": "m", 80 | "member": 1, 81 | "position": 30, 82 | "x_mag": 0, 83 | "y_mag": -10, 84 | "z_mag": 0, 85 | "load_group": "LG1" 86 | }, 87 | }, 88 | } 89 | 90 | # Creating the functions array 91 | functions = [ 92 | { 93 | "function": "S3D.session.start", 94 | "arguments": { 95 | "keep_open": False 96 | } 97 | }, 98 | { 99 | "function": "S3D.model.set", 100 | "arguments": { 101 | "s3d_model": s3d_model 102 | } 103 | }, 104 | { 105 | "function": "S3D.model.solve", 106 | "arguments": { 107 | "analysis_type": "linear", 108 | } 109 | }, 110 | { 111 | "function": "S3D.design.member.check", 112 | "arguments": { 113 | "design_code": "AS_4100-1998", 114 | "s3d_model": s3d_model, 115 | } 116 | }, 117 | { 118 | "function": "S3D.file.save", 119 | "arguments": { 120 | "name": "simple-beam-test", 121 | "path": "api/intro-to-programming/" 122 | } 123 | } 124 | ] 125 | 126 | # Adding the functions array to the api object 127 | api_object["functions"] = functions 128 | 129 | # Import the skyciv package at the top of this script 130 | 131 | # Make the call! 132 | res = skyciv.request(api_object) 133 | 134 | # Add it to a file for inspection 135 | with open("lessons/17-interpreting-the-response/pyOutput.json", "w") as f: 136 | print(res, file=f) 137 | 138 | # ========== THIS LESSON ======================================================================= 139 | 140 | # Loop the functions array 141 | 142 | for fn in res["functions"]: 143 | 144 | # Check if fn is the solve function 145 | if (fn["function"] == "S3D.model.solve"): 146 | # Do something with the function results 147 | loadGroup1 = fn["data"]["0"] 148 | 149 | # Get peak displacements 150 | peakResults = loadGroup1["member_peak_results"] 151 | peakDispMinY = peakResults["displacement_local_y"]["min"] 152 | peakDispMaxY = peakResults["displacement_local_y"]["max"] 153 | 154 | # Get max stress 155 | memberMaximums = loadGroup1["member_maximums"] 156 | topCombinedStressZ = memberMaximums["top_combined_stress_z"]["1"] 157 | btmCombinedStressZ = memberMaximums["btm_combined_stress_z"]["1"] 158 | 159 | # Check deflection criteria 160 | allowableDisp = 5000 / 300 # ~16.67 161 | maxDispPass = abs(peakDispMaxY) < allowableDisp 162 | minDispPass = abs(peakDispMinY) < allowableDisp 163 | 164 | if (maxDispPass and minDispPass): 165 | print("Displacement is ok! :D") 166 | else: 167 | print("Displacement criteria failed :(") 168 | 169 | # Check stress criteria 170 | allowableStress = 270 # Say 270MPa 171 | topStressPass = abs(topCombinedStressZ) < allowableStress 172 | btmStressPass = abs(btmCombinedStressZ) < allowableStress 173 | 174 | if (topStressPass and btmStressPass): 175 | print("Stress criteria passed! :)") 176 | else: 177 | print("Stress criteria failed! :(") 178 | -------------------------------------------------------------------------------- /lessons/17-interpreting-the-response/jsOutput.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "data": "https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 4 | "msg": "Model was successfully saved to your SkyCiv cloud storage in the folder api/intro-to-programming/. You can access this file from your SkyCiv Dashboard, or directly from https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 5 | "status": 0, 6 | "function": "S3D.file.save", 7 | "last_session_id": "wi5t6Y3tUUvV6fKu92NpXDSy2GlnOITPPfem14Adol7Bz4vAoXInBGhxihGWXLw4_1", 8 | "monthly_api_credits": { "quota": 6000, "total_used": 40, "used_this_call": 2 } 9 | }, 10 | "functions": [ 11 | { 12 | "session_id": "wi5t6Y3tUUvV6fKu92NpXDSy2GlnOITPPfem14Adol7Bz4vAoXInBGhxihGWXLw4_1", 13 | "session_expiry_time": 1610426021, 14 | "msg": "S3D session successfully started.", 15 | "status": 0, 16 | "function": "S3D.session.start", 17 | "data": "" 18 | }, 19 | { 20 | "msg": "Model was successfully set.", 21 | "status": 0, 22 | "function": "S3D.model.set", 23 | "data": "" 24 | }, 25 | { 26 | "data": { 27 | "0": { 28 | "name": "LG1", 29 | "type": "load_group", 30 | "reactions": { 31 | "1": { "Fx": 0, "Fy": 8.785, "Fz": 0, "Mx": 0, "My": 0, "Mz": 8.925 }, 32 | "2": { "Fx": 0, "Fy": 1.215, "Fz": 0, "Mx": 0, "My": 0, "Mz": 0 } 33 | }, 34 | "member_displacements": { 35 | "displacement_x": { 36 | "1": { 37 | "0.0": 0, 38 | "7.1": 0, 39 | "14.3": 0, 40 | "21.4": 0, 41 | "28.6": 0, 42 | "30.0": 0, 43 | "35.7": 0, 44 | "42.9": 0, 45 | "50.0": 0, 46 | "57.1": 0, 47 | "64.3": 0, 48 | "71.4": 0, 49 | "78.6": 0, 50 | "85.7": 0, 51 | "92.9": 0, 52 | "100.0": 0 53 | } 54 | }, 55 | "displacement_y": { 56 | "1": { 57 | "0.0": 0, 58 | "7.1": -0.278, 59 | "14.3": -0.963, 60 | "21.4": -1.835, 61 | "28.6": -2.673, 62 | "30.0": -2.817, 63 | "35.7": -3.277, 64 | "42.9": -3.606, 65 | "50.0": -3.69, 66 | "57.1": -3.561, 67 | "64.3": -3.248, 68 | "71.4": -2.782, 69 | "78.6": -2.193, 70 | "85.7": -1.513, 71 | "92.9": -0.772, 72 | "100.0": 0 73 | } 74 | }, 75 | "displacement_z": { 76 | "1": { 77 | "0.0": 0, 78 | "7.1": 0, 79 | "14.3": 0, 80 | "21.4": 0, 81 | "28.6": 0, 82 | "30.0": 0, 83 | "35.7": 0, 84 | "42.9": 0, 85 | "50.0": 0, 86 | "57.1": 0, 87 | "64.3": 0, 88 | "71.4": 0, 89 | "78.6": 0, 90 | "85.7": 0, 91 | "92.9": 0, 92 | "100.0": 0 93 | } 94 | }, 95 | "displacement_sum": { 96 | "1": { 97 | "0.0": 0, 98 | "7.1": 0.278, 99 | "14.3": 0.963, 100 | "21.4": 1.835, 101 | "28.6": 2.673, 102 | "30.0": 2.817, 103 | "35.7": 3.277, 104 | "42.9": 3.606, 105 | "50.0": 3.69, 106 | "57.1": 3.561, 107 | "64.3": 3.248, 108 | "71.4": 2.782, 109 | "78.6": 2.193, 110 | "85.7": 1.513, 111 | "92.9": 0.772, 112 | "100.0": 0 113 | } 114 | }, 115 | "displacement_local_x": { 116 | "1": { 117 | "0.0": 0, 118 | "7.1": 0, 119 | "14.3": 0, 120 | "21.4": 0, 121 | "28.6": 0, 122 | "30.0": 0, 123 | "35.7": 0, 124 | "42.9": 0, 125 | "50.0": 0, 126 | "57.1": 0, 127 | "64.3": 0, 128 | "71.4": 0, 129 | "78.6": 0, 130 | "85.7": 0, 131 | "92.9": 0, 132 | "100.0": 0 133 | } 134 | }, 135 | "displacement_local_y": { 136 | "1": { 137 | "0.0": 0, 138 | "7.1": -0.278, 139 | "14.3": -0.963, 140 | "21.4": -1.835, 141 | "28.6": -2.673, 142 | "30.0": -2.817, 143 | "35.7": -3.277, 144 | "42.9": -3.606, 145 | "50.0": -3.69, 146 | "57.1": -3.561, 147 | "64.3": -3.248, 148 | "71.4": -2.782, 149 | "78.6": -2.193, 150 | "85.7": -1.513, 151 | "92.9": -0.772, 152 | "100.0": 0 153 | } 154 | }, 155 | "displacement_local_z": { 156 | "1": { 157 | "0.0": 0, 158 | "7.1": 0, 159 | "14.3": 0, 160 | "21.4": 0, 161 | "28.6": 0, 162 | "30.0": 0, 163 | "35.7": 0, 164 | "42.9": 0, 165 | "50.0": 0, 166 | "57.1": 0, 167 | "64.3": 0, 168 | "71.4": 0, 169 | "78.6": 0, 170 | "85.7": 0, 171 | "92.9": 0, 172 | "100.0": 0 173 | } 174 | }, 175 | "displacement_local_sum": { 176 | "1": { 177 | "0.0": 0, 178 | "7.1": 0.278, 179 | "14.3": 0.963, 180 | "21.4": 1.835, 181 | "28.6": 2.673, 182 | "30.0": 2.817, 183 | "35.7": 3.277, 184 | "42.9": 3.606, 185 | "50.0": 3.69, 186 | "57.1": 3.561, 187 | "64.3": 3.248, 188 | "71.4": 2.782, 189 | "78.6": 2.193, 190 | "85.7": 1.513, 191 | "92.9": 0.772, 192 | "100.0": 0 193 | } 194 | }, 195 | "rotation_x": { 196 | "1": { 197 | "0.0": 0, 198 | "7.1": 0, 199 | "14.3": 0, 200 | "21.4": 0, 201 | "28.6": 0, 202 | "30.0": 0, 203 | "35.7": 0, 204 | "42.9": 0, 205 | "50.0": 0, 206 | "57.1": 0, 207 | "64.3": 0, 208 | "71.4": 0, 209 | "78.6": 0, 210 | "85.7": 0, 211 | "92.9": 0, 212 | "100.0": 0 213 | } 214 | }, 215 | "rotation_y": { 216 | "1": { 217 | "0.0": 0, 218 | "7.1": 0, 219 | "14.3": 0, 220 | "21.4": 0, 221 | "28.6": 0, 222 | "30.0": 0, 223 | "35.7": 0, 224 | "42.9": 0, 225 | "50.0": 0, 226 | "57.1": 0, 227 | "64.3": 0, 228 | "71.4": 0, 229 | "78.6": 0, 230 | "85.7": 0, 231 | "92.9": 0, 232 | "100.0": 0 233 | } 234 | }, 235 | "rotation_z": { 236 | "1": { 237 | "0.0": 0, 238 | "7.1": -0.001, 239 | "14.3": -0.002, 240 | "21.4": -0.002, 241 | "28.6": -0.002, 242 | "30.0": -0.002, 243 | "35.7": -0.001, 244 | "42.9": -0.001, 245 | "50.0": 0, 246 | "57.1": 0.001, 247 | "64.3": 0.001, 248 | "71.4": 0.001, 249 | "78.6": 0.002, 250 | "85.7": 0.002, 251 | "92.9": 0.002, 252 | "100.0": 0.002 253 | } 254 | }, 255 | "rotation_local_x": { 256 | "1": { 257 | "0.0": 0, 258 | "7.1": 0, 259 | "14.3": 0, 260 | "21.4": 0, 261 | "28.6": 0, 262 | "30.0": 0, 263 | "35.7": 0, 264 | "42.9": 0, 265 | "50.0": 0, 266 | "57.1": 0, 267 | "64.3": 0, 268 | "71.4": 0, 269 | "78.6": 0, 270 | "85.7": 0, 271 | "92.9": 0, 272 | "100.0": 0 273 | } 274 | }, 275 | "rotation_local_y": { 276 | "1": { 277 | "0.0": 0, 278 | "7.1": 0, 279 | "14.3": 0, 280 | "21.4": 0, 281 | "28.6": 0, 282 | "30.0": 0, 283 | "35.7": 0, 284 | "42.9": 0, 285 | "50.0": 0, 286 | "57.1": 0, 287 | "64.3": 0, 288 | "71.4": 0, 289 | "78.6": 0, 290 | "85.7": 0, 291 | "92.9": 0, 292 | "100.0": 0 293 | } 294 | }, 295 | "rotation_local_z": { 296 | "1": { 297 | "0.0": 0, 298 | "7.1": -0.001, 299 | "14.3": -0.002, 300 | "21.4": -0.002, 301 | "28.6": -0.002, 302 | "30.0": -0.002, 303 | "35.7": -0.001, 304 | "42.9": -0.001, 305 | "50.0": 0, 306 | "57.1": 0.001, 307 | "64.3": 0.001, 308 | "71.4": 0.001, 309 | "78.6": 0.002, 310 | "85.7": 0.002, 311 | "92.9": 0.002, 312 | "100.0": 0.002 313 | } 314 | } 315 | }, 316 | "member_forces": { 317 | "axial_force": { 318 | "1": { 319 | "0.0": 0, 320 | "7.1": 0, 321 | "14.3": 0, 322 | "21.4": 0, 323 | "28.6": 0, 324 | "30.0": 0, 325 | "35.7": 0, 326 | "42.9": 0, 327 | "50.0": 0, 328 | "57.1": 0, 329 | "64.3": 0, 330 | "71.4": 0, 331 | "78.6": 0, 332 | "85.7": 0, 333 | "92.9": 0, 334 | "100.0": 0 335 | } 336 | }, 337 | "shear_force_y": { 338 | "1": { 339 | "0.0": 8.785, 340 | "7.1": 8.785, 341 | "14.3": 8.785, 342 | "21.4": 8.785, 343 | "28.6": 8.785, 344 | "30.0": [8.785, -1.215], 345 | "35.7": -1.215, 346 | "42.9": -1.215, 347 | "50.0": -1.215, 348 | "57.1": -1.215, 349 | "64.3": -1.215, 350 | "71.4": -1.215, 351 | "78.6": -1.215, 352 | "85.7": -1.215, 353 | "92.9": -1.215, 354 | "100.0": -1.215 355 | } 356 | }, 357 | "shear_force_z": { 358 | "1": { 359 | "0.0": 0, 360 | "7.1": 0, 361 | "14.3": 0, 362 | "21.4": 0, 363 | "28.6": 0, 364 | "30.0": 0, 365 | "35.7": 0, 366 | "42.9": 0, 367 | "50.0": 0, 368 | "57.1": 0, 369 | "64.3": 0, 370 | "71.4": 0, 371 | "78.6": 0, 372 | "85.7": 0, 373 | "92.9": 0, 374 | "100.0": 0 375 | } 376 | }, 377 | "bending_moment_y": { 378 | "1": { 379 | "0.0": 0, 380 | "7.1": 0, 381 | "14.3": 0, 382 | "21.4": 0, 383 | "28.6": 0, 384 | "30.0": 0, 385 | "35.7": 0, 386 | "42.9": 0, 387 | "50.0": 0, 388 | "57.1": 0, 389 | "64.3": 0, 390 | "71.4": 0, 391 | "78.6": 0, 392 | "85.7": 0, 393 | "92.9": 0, 394 | "100.0": 0 395 | } 396 | }, 397 | "bending_moment_z": { 398 | "1": { 399 | "0.0": -8.925, 400 | "7.1": -5.787, 401 | "14.3": -2.65, 402 | "21.4": 0.487, 403 | "28.6": 3.625, 404 | "30.0": 4.253, 405 | "35.7": 3.905, 406 | "42.9": 3.471, 407 | "50.0": 3.038, 408 | "57.1": 2.604, 409 | "64.3": 2.17, 410 | "71.4": 1.736, 411 | "78.6": 1.302, 412 | "85.7": 0.868, 413 | "92.9": 0.434, 414 | "100.0": 0 415 | } 416 | }, 417 | "torsion": { 418 | "1": { 419 | "0.0": 0, 420 | "7.1": 0, 421 | "14.3": 0, 422 | "21.4": 0, 423 | "28.6": 0, 424 | "30.0": 0, 425 | "35.7": 0, 426 | "42.9": 0, 427 | "50.0": 0, 428 | "57.1": 0, 429 | "64.3": 0, 430 | "71.4": 0, 431 | "78.6": 0, 432 | "85.7": 0, 433 | "92.9": 0, 434 | "100.0": 0 435 | } 436 | } 437 | }, 438 | "member_stresses": { 439 | "axial_stress": { 440 | "1": { 441 | "0.0": 0, 442 | "7.1": 0, 443 | "14.3": 0, 444 | "21.4": 0, 445 | "28.6": 0, 446 | "30.0": 0, 447 | "35.7": 0, 448 | "42.9": 0, 449 | "50.0": 0, 450 | "57.1": 0, 451 | "64.3": 0, 452 | "71.4": 0, 453 | "78.6": 0, 454 | "85.7": 0, 455 | "92.9": 0, 456 | "100.0": 0 457 | } 458 | }, 459 | "top_bending_stress_z": { 460 | "1": { 461 | "0.0": -76.43, 462 | "7.1": -49.561, 463 | "14.3": -22.693, 464 | "21.4": 4.175, 465 | "28.6": 31.043, 466 | "30.0": 36.416, 467 | "35.7": 33.444, 468 | "42.9": 29.728, 469 | "50.0": 26.012, 470 | "57.1": 22.296, 471 | "64.3": 18.58, 472 | "71.4": 14.864, 473 | "78.6": 11.148, 474 | "85.7": 7.432, 475 | "92.9": 3.716, 476 | "100.0": 0 477 | } 478 | }, 479 | "top_bending_stress_y": { 480 | "1": { 481 | "0.0": 0, 482 | "7.1": 0, 483 | "14.3": 0, 484 | "21.4": 0, 485 | "28.6": 0, 486 | "30.0": 0, 487 | "35.7": 0, 488 | "42.9": 0, 489 | "50.0": 0, 490 | "57.1": 0, 491 | "64.3": 0, 492 | "71.4": 0, 493 | "78.6": 0, 494 | "85.7": 0, 495 | "92.9": 0, 496 | "100.0": 0 497 | } 498 | }, 499 | "btm_bending_stress_z": { 500 | "1": { 501 | "0.0": 76.43, 502 | "7.1": 49.561, 503 | "14.3": 22.693, 504 | "21.4": -4.175, 505 | "28.6": -31.043, 506 | "30.0": -36.416, 507 | "35.7": -33.444, 508 | "42.9": -29.728, 509 | "50.0": -26.012, 510 | "57.1": -22.296, 511 | "64.3": -18.58, 512 | "71.4": -14.864, 513 | "78.6": -11.148, 514 | "85.7": -7.432, 515 | "92.9": -3.716, 516 | "100.0": 0 517 | } 518 | }, 519 | "btm_bending_stress_y": { 520 | "1": { 521 | "0.0": 0, 522 | "7.1": 0, 523 | "14.3": 0, 524 | "21.4": 0, 525 | "28.6": 0, 526 | "30.0": 0, 527 | "35.7": 0, 528 | "42.9": 0, 529 | "50.0": 0, 530 | "57.1": 0, 531 | "64.3": 0, 532 | "71.4": 0, 533 | "78.6": 0, 534 | "85.7": 0, 535 | "92.9": 0, 536 | "100.0": 0 537 | } 538 | }, 539 | "shear_stress_z": { 540 | "1": { 541 | "0.0": 0, 542 | "7.1": 0, 543 | "14.3": 0, 544 | "21.4": 0, 545 | "28.6": 0, 546 | "30.0": 0, 547 | "35.7": 0, 548 | "42.9": 0, 549 | "50.0": 0, 550 | "57.1": 0, 551 | "64.3": 0, 552 | "71.4": 0, 553 | "78.6": 0, 554 | "85.7": 0, 555 | "92.9": 0, 556 | "100.0": 0 557 | } 558 | }, 559 | "shear_stress_y": { 560 | "1": { 561 | "0.0": 9.792, 562 | "7.1": 9.792, 563 | "14.3": 9.792, 564 | "21.4": 9.792, 565 | "28.6": 9.792, 566 | "30.0": [9.792, -1.354], 567 | "35.7": -1.354, 568 | "42.9": -1.354, 569 | "50.0": -1.354, 570 | "57.1": -1.354, 571 | "64.3": -1.354, 572 | "71.4": -1.354, 573 | "78.6": -1.354, 574 | "85.7": -1.354, 575 | "92.9": -1.354, 576 | "100.0": -1.354 577 | } 578 | }, 579 | "torsion_stress": { 580 | "1": { 581 | "0.0": 0, 582 | "7.1": 0, 583 | "14.3": 0, 584 | "21.4": 0, 585 | "28.6": 0, 586 | "30.0": 0, 587 | "35.7": 0, 588 | "42.9": 0, 589 | "50.0": 0, 590 | "57.1": 0, 591 | "64.3": 0, 592 | "71.4": 0, 593 | "78.6": 0, 594 | "85.7": 0, 595 | "92.9": 0, 596 | "100.0": 0 597 | } 598 | }, 599 | "top_combined_stress_z": { 600 | "1": { 601 | "0.0": -76.43, 602 | "7.1": -49.561, 603 | "14.3": -22.693, 604 | "21.4": 4.175, 605 | "28.6": 31.043, 606 | "30.0": 36.416, 607 | "35.7": 33.444, 608 | "42.9": 29.728, 609 | "50.0": 26.012, 610 | "57.1": 22.296, 611 | "64.3": 18.58, 612 | "71.4": 14.864, 613 | "78.6": 11.148, 614 | "85.7": 7.432, 615 | "92.9": 3.716, 616 | "100.0": 0 617 | } 618 | }, 619 | "top_combined_stress_y": { 620 | "1": { 621 | "0.0": 0, 622 | "7.1": 0, 623 | "14.3": 0, 624 | "21.4": 0, 625 | "28.6": 0, 626 | "30.0": 0, 627 | "35.7": 0, 628 | "42.9": 0, 629 | "50.0": 0, 630 | "57.1": 0, 631 | "64.3": 0, 632 | "71.4": 0, 633 | "78.6": 0, 634 | "85.7": 0, 635 | "92.9": 0, 636 | "100.0": 0 637 | } 638 | }, 639 | "btm_combined_stress_z": { 640 | "1": { 641 | "0.0": 76.43, 642 | "7.1": 49.561, 643 | "14.3": 22.693, 644 | "21.4": -4.175, 645 | "28.6": -31.043, 646 | "30.0": -36.416, 647 | "35.7": -33.444, 648 | "42.9": -29.728, 649 | "50.0": -26.012, 650 | "57.1": -22.296, 651 | "64.3": -18.58, 652 | "71.4": -14.864, 653 | "78.6": -11.148, 654 | "85.7": -7.432, 655 | "92.9": -3.716, 656 | "100.0": 0 657 | } 658 | }, 659 | "btm_combined_stress_y": { 660 | "1": { 661 | "0.0": 0, 662 | "7.1": 0, 663 | "14.3": 0, 664 | "21.4": 0, 665 | "28.6": 0, 666 | "30.0": 0, 667 | "35.7": 0, 668 | "42.9": 0, 669 | "50.0": 0, 670 | "57.1": 0, 671 | "64.3": 0, 672 | "71.4": 0, 673 | "78.6": 0, 674 | "85.7": 0, 675 | "92.9": 0, 676 | "100.0": 0 677 | } 678 | } 679 | }, 680 | "member_lengths": { "1": 5 }, 681 | "member_stations": { 682 | "1": [ 683 | 0, 684 | 7.142857142857143, 685 | 14.285714285714286, 686 | 21.428571428571427, 687 | 28.571428571428573, 688 | 30, 689 | 35.714285714285715, 690 | 42.857142857142854, 691 | 50, 692 | 57.142857142857146, 693 | 64.28571428571429, 694 | 71.42857142857143, 695 | 78.57142857142857, 696 | 85.71428571428571, 697 | 92.85714285714286, 698 | 100 699 | ] 700 | }, 701 | "member_discontinuities": { "1": 1 }, 702 | "member_minimums": { 703 | "displacement_x": { "1": 0 }, 704 | "displacement_y": { "1": -3.69043508 }, 705 | "displacement_z": { "1": 0 }, 706 | "displacement_sum": { "1": 0 }, 707 | "displacement_local_x": { "1": 0 }, 708 | "displacement_local_y": { "1": -3.69043508 }, 709 | "displacement_local_z": { "1": 0 }, 710 | "displacement_local_sum": { "1": 0 }, 711 | "displacement_relative": { "1": 0 }, 712 | "displacement_relative_local_x": { "1": 0 }, 713 | "displacement_relative_local_y": { "1": -3.69043508 }, 714 | "displacement_relative_local_z": { "1": 0 }, 715 | "displacement_span_ratio": { "1": 1354 }, 716 | "displacement_span_ratio_2": { "1": 1354 }, 717 | "rotation_x": { "1": 0 }, 718 | "rotation_y": { "1": 0 }, 719 | "rotation_z": { "1": -0.0024972869 }, 720 | "rotation_local_x": { "1": 0 }, 721 | "rotation_local_y": { "1": 0 }, 722 | "rotation_local_z": { "1": -0.0024972869 }, 723 | "axial_force": { "1": 0 }, 724 | "shear_force_y": { "1": -1.215 }, 725 | "shear_force_z": { "1": 0 }, 726 | "torsion": { "1": 0 }, 727 | "bending_moment_y": { "1": 0 }, 728 | "bending_moment_z": { "1": -8.925 }, 729 | "top_bending_stress_z": { "1": -76.42955801 }, 730 | "top_bending_stress_y": { "1": 0 }, 731 | "btm_bending_stress_z": { "1": -36.41643646 }, 732 | "btm_bending_stress_y": { "1": 0 }, 733 | "shear_stress_z": { "1": 0 }, 734 | "shear_stress_y": { "1": -1.35430098 }, 735 | "axial_stress": { "1": 0 }, 736 | "top_combined_stress_z": { "1": -76.42955801 }, 737 | "top_combined_stress_y": { "1": 0 }, 738 | "btm_combined_stress_z": { "1": -36.41643646 }, 739 | "btm_combined_stress_y": { "1": 0 }, 740 | "torsion_stress": { "1": 0 } 741 | }, 742 | "member_maximums": { 743 | "displacement_x": { "1": 0 }, 744 | "displacement_y": { "1": 0 }, 745 | "displacement_z": { "1": 0 }, 746 | "displacement_sum": { "1": 3.69043508 }, 747 | "displacement_local_x": { "1": 0 }, 748 | "displacement_local_y": { "1": 0 }, 749 | "displacement_local_z": { "1": 0 }, 750 | "displacement_local_sum": { "1": 3.69043508 }, 751 | "displacement_relative": { "1": 3.69043508 }, 752 | "displacement_relative_local_x": { "1": 0 }, 753 | "displacement_relative_local_y": { "1": 0 }, 754 | "displacement_relative_local_z": { "1": 0 }, 755 | "displacement_span_ratio": { "1": 1000000000000 }, 756 | "displacement_span_ratio_2": { "1": 1354 }, 757 | "rotation_x": { "1": 0 }, 758 | "rotation_y": { "1": 0 }, 759 | "rotation_z": { "1": 0.0021754144 }, 760 | "rotation_local_x": { "1": 0 }, 761 | "rotation_local_y": { "1": 0 }, 762 | "rotation_local_z": { "1": 0.0021754144 }, 763 | "axial_force": { "1": 0 }, 764 | "shear_force_y": { "1": 8.785 }, 765 | "shear_force_z": { "1": 0 }, 766 | "torsion": { "1": 0 }, 767 | "bending_moment_y": { "1": 0 }, 768 | "bending_moment_z": { "1": 4.2525 }, 769 | "top_bending_stress_z": { "1": 36.41643646 }, 770 | "top_bending_stress_y": { "1": 0 }, 771 | "btm_bending_stress_z": { "1": 76.42955801 }, 772 | "btm_bending_stress_y": { "1": 0 }, 773 | "shear_stress_z": { "1": 0 }, 774 | "shear_stress_y": { "1": 9.79220912 }, 775 | "axial_stress": { "1": 0 }, 776 | "top_combined_stress_z": { "1": 36.41643646 }, 777 | "top_combined_stress_y": { "1": 0 }, 778 | "btm_combined_stress_z": { "1": 76.42955801 }, 779 | "btm_combined_stress_y": { "1": 0 }, 780 | "torsion_stress": { "1": 0 } 781 | }, 782 | "member_peak_results": { 783 | "displacement_x": { "min": 0, "max": 0 }, 784 | "displacement_y": { "min": -3.69043508, "max": 0 }, 785 | "displacement_z": { "min": 0, "max": 0 }, 786 | "displacement_sum": { "min": 0, "max": 3.69043508 }, 787 | "displacement_local_x": { "min": 0, "max": 0 }, 788 | "displacement_local_y": { "min": -3.69043508, "max": 0 }, 789 | "displacement_local_z": { "min": 0, "max": 0 }, 790 | "displacement_local_sum": { "min": 0, "max": 3.69043508 }, 791 | "displacement_relative": { "min": 0, "max": 3.69043508 }, 792 | "displacement_relative_local_x": { "min": 0, "max": 0 }, 793 | "displacement_relative_local_y": { "min": -3.69043508, "max": 0 }, 794 | "displacement_relative_local_z": { "min": 0, "max": 0 }, 795 | "displacement_span_ratio": { "min": 1354, "max": 1000000000000 }, 796 | "displacement_span_ratio_2": { "min": 1354, "max": 1354 }, 797 | "rotation_x": { "min": 0, "max": 0 }, 798 | "rotation_y": { "min": 0, "max": 0 }, 799 | "rotation_z": { "min": -0.0024972869, "max": 0.0021754144 }, 800 | "rotation_local_x": { "min": 0, "max": 0 }, 801 | "rotation_local_y": { "min": 0, "max": 0 }, 802 | "rotation_local_z": { "min": -0.0024972869, "max": 0.0021754144 }, 803 | "axial_force": { "min": 0, "max": 0 }, 804 | "shear_force_y": { "min": -1.215, "max": 8.785 }, 805 | "shear_force_z": { "min": 0, "max": 0 }, 806 | "torsion": { "min": 0, "max": 0 }, 807 | "bending_moment_y": { "min": 0, "max": 0 }, 808 | "bending_moment_z": { "min": -8.925, "max": 4.2525 }, 809 | "top_bending_stress_z": { "min": -76.42955801, "max": 36.41643646 }, 810 | "top_bending_stress_y": { "min": 0, "max": 0 }, 811 | "btm_bending_stress_z": { "min": -36.41643646, "max": 76.42955801 }, 812 | "btm_bending_stress_y": { "min": 0, "max": 0 }, 813 | "shear_stress_z": { "min": 0, "max": 0 }, 814 | "shear_stress_y": { "min": -1.35430098, "max": 9.79220912 }, 815 | "axial_stress": { "min": 0, "max": 0 }, 816 | "top_combined_stress_z": { "min": -76.42955801, "max": 36.41643646 }, 817 | "top_combined_stress_y": { "min": 0, "max": 0 }, 818 | "btm_combined_stress_z": { "min": -36.41643646, "max": 76.42955801 }, 819 | "btm_combined_stress_y": { "min": 0, "max": 0 }, 820 | "torsion_stress": { "min": 0, "max": 0 } 821 | }, 822 | "plate_displacements": { 823 | "displacement_x": {}, 824 | "displacement_y": {}, 825 | "displacement_z": {}, 826 | "displacement_sum": {} 827 | }, 828 | "plate_forces": { 829 | "force_x": {}, 830 | "force_xy": {}, 831 | "force_xz": {}, 832 | "force_y": {}, 833 | "force_yz": {}, 834 | "moment_x": {}, 835 | "moment_xy": {}, 836 | "moment_y": {} 837 | }, 838 | "plate_stresses": { 839 | "stress_major_principal_top": {}, 840 | "stress_max_shear_top": {}, 841 | "stress_minor_principal_top": {}, 842 | "stress_von_mises_top": {}, 843 | "stress_xx_top": {}, 844 | "stress_yy_top": {}, 845 | "stress_xy_top": {}, 846 | "stress_major_principal_btm": {}, 847 | "stress_max_shear_btm": {}, 848 | "stress_minor_principal_btm": {}, 849 | "stress_von_mises_btm": {}, 850 | "stress_xx_btm": {}, 851 | "stress_yy_btm": {}, 852 | "stress_xy_btm": {} 853 | }, 854 | "plate_minimums": {}, 855 | "plate_maximums": {}, 856 | "plate_peak_results": { 857 | "displacement_x": { "min": 0, "max": 0 }, 858 | "displacement_y": { "min": 0, "max": 0 }, 859 | "displacement_z": { "min": 0, "max": 0 }, 860 | "displacement_sum": { "min": 0, "max": 0 }, 861 | "stress_xx_top": { "min": 0, "max": 0 }, 862 | "stress_xx_btm": { "min": 0, "max": 0 }, 863 | "stress_yy_top": { "min": 0, "max": 0 }, 864 | "stress_yy_btm": { "min": 0, "max": 0 }, 865 | "stress_xy_top": { "min": 0, "max": 0 }, 866 | "stress_xy_btm": { "min": 0, "max": 0 }, 867 | "stress_major_principal_top": { "min": 0, "max": 0 }, 868 | "stress_major_principal_btm": { "min": 0, "max": 0 }, 869 | "stress_minor_principal_top": { "min": 0, "max": 0 }, 870 | "stress_minor_principal_btm": { "min": 0, "max": 0 }, 871 | "stress_von_mises_top": { "min": 0, "max": 0 }, 872 | "stress_von_mises_btm": { "min": 0, "max": 0 }, 873 | "stress_max_shear_top": { "min": 0, "max": 0 }, 874 | "stress_max_shear_btm": { "min": 0, "max": 0 }, 875 | "force_x": { "min": 0, "max": 0 }, 876 | "force_y": { "min": 0, "max": 0 }, 877 | "force_xy": { "min": 0, "max": 0 }, 878 | "force_xz": { "min": 0, "max": 0 }, 879 | "force_yz": { "min": 0, "max": 0 }, 880 | "moment_x": { "min": 0, "max": 0 }, 881 | "moment_y": { "min": 0, "max": 0 }, 882 | "moment_xy": { "min": 0, "max": 0 } 883 | }, 884 | "buckling": "disabled", 885 | "dynamic_frequency": "disabled" 886 | } 887 | }, 888 | "msg": "Solved Successfully!", 889 | "comments": " Linear Static Analysis Completed ", 890 | "status": 0, 891 | "function": "S3D.model.solve" 892 | }, 893 | { 894 | "data": { 895 | "capacity": { 896 | "axial_tension": { "1": 538.2 }, 897 | "axial_compression": { "1": 538.2 }, 898 | "moment_z": { "1": 31.590000000000003 }, 899 | "moment_y": { "1": 6.289919999999986 }, 900 | "shear_y": { "1": 130.572 }, 901 | "shear_z": { "1": 200.07 }, 902 | "axial_buckling": { "1": 68.36937702415861 }, 903 | "flexure_buckling": { "1": 11.498996211214772 } 904 | }, 905 | "ratio": { 906 | "axial": { "1": 0 }, 907 | "moment_z": { "1": 0.2825261158594492 }, 908 | "moment_y": { "1": 0 }, 909 | "shear_y": { "1": 0.0672808871733603 }, 910 | "shear_z": { "1": 0 }, 911 | "buckling_compression": { "1": 0 }, 912 | "buckling_bending": { "1": 0.7761547039467326 }, 913 | "combined_strength": { "1": 0.2825261158594492 }, 914 | "combined_buckling": { "1": 0.7761547039467326 }, 915 | "slender": { "1": 0.7800420555749596 }, 916 | "worstlc": { "1": "#1" }, 917 | "displacement": { "1": 0.18452200000000002 } 918 | }, 919 | "html_summary_link": "https://solver.skyciv.com/temp/view_report_hvxqKB8iLq3HvdE5.php", 920 | "html_download_link": "https://solver.skyciv.com/temp/download_html_report_hvxqKB8iLq3HvdE5.php", 921 | "pdf_download_link": "https://solver.skyciv.com/temp/download_report_hvxqKB8iLq3HvdE5.php", 922 | "reports": { 923 | "1": { 924 | "html_view_link": "https://solver.skyciv.com/temp/view_report_hvxqKB8iLq3HvdE5_0.php", 925 | "html_download_link": "https://solver.skyciv.com/temp/download_html_report_hvxqKB8iLq3HvdE5_0.php", 926 | "pdf_download_link": "https://solver.skyciv.com/temp/download_report_hvxqKB8iLq3HvdE5_0.php" 927 | } 928 | }, 929 | "summary": { 930 | "failed_members": [], 931 | "passed_members": ["1"], 932 | "critical": { 933 | "utility_ratio": 0.7800420555749596, 934 | "member_id": "1", 935 | "action": "slender", 936 | "load_case": "#1", 937 | "status": "PASS" 938 | } 939 | } 940 | }, 941 | "msg": "Member Design check for AS_4100-1998 was run successfully.", 942 | "status": 0, 943 | "function": "S3D.design.member.check" 944 | }, 945 | { 946 | "data": "https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 947 | "msg": "Model was successfully saved to your SkyCiv cloud storage in the folder api/intro-to-programming/. You can access this file from your SkyCiv Dashboard, or directly from https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 948 | "status": 0, 949 | "function": "S3D.file.save" 950 | } 951 | ] 952 | } 953 | -------------------------------------------------------------------------------- /lessons/17-interpreting-the-response/pyOutput.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "data": "https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 4 | "msg": "Model was successfully saved to your SkyCiv cloud storage in the folder api/intro-to-programming/. You can access this file from your SkyCiv Dashboard, or directly from https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 5 | "status": 0, 6 | "function": "S3D.file.save", 7 | "last_session_id": "ehJAf6PzEFgblD5Ar0zlpEA5mmSo9eEtwSmhbau1gy6qRSlLvqgrleabzvLrgbza_2", 8 | "monthly_api_credits": { "quota": 6000, "total_used": 59, "used_this_call": 2 } 9 | }, 10 | "functions": [ 11 | { 12 | "session_id": "ehJAf6PzEFgblD5Ar0zlpEA5mmSo9eEtwSmhbau1gy6qRSlLvqgrleabzvLrgbza_2", 13 | "session_expiry_time": 1611012625, 14 | "msg": "S3D session successfully started.", 15 | "status": 0, 16 | "function": "S3D.session.start", 17 | "data": "" 18 | }, 19 | { 20 | "msg": "Model was successfully set.", 21 | "status": 0, 22 | "function": "S3D.model.set", 23 | "data": "" 24 | }, 25 | { 26 | "data": { 27 | "0": { 28 | "name": "LG1", 29 | "type": "load_group", 30 | "reactions": { 31 | "1": { "Fx": 0, "Fy": 8.785, "Fz": 0, "Mx": 0, "My": 0, "Mz": 8.925 }, 32 | "2": { "Fx": 0, "Fy": 1.215, "Fz": 0, "Mx": 0, "My": 0, "Mz": 0 } 33 | }, 34 | "member_displacements": { 35 | "displacement_x": { 36 | "1": { 37 | "0.0": 0, 38 | "7.1": 0, 39 | "14.3": 0, 40 | "21.4": 0, 41 | "28.6": 0, 42 | "30.0": 0, 43 | "35.7": 0, 44 | "42.9": 0, 45 | "50.0": 0, 46 | "57.1": 0, 47 | "64.3": 0, 48 | "71.4": 0, 49 | "78.6": 0, 50 | "85.7": 0, 51 | "92.9": 0, 52 | "100.0": 0 53 | } 54 | }, 55 | "displacement_y": { 56 | "1": { 57 | "0.0": 0, 58 | "7.1": -0.278, 59 | "14.3": -0.963, 60 | "21.4": -1.835, 61 | "28.6": -2.673, 62 | "30.0": -2.817, 63 | "35.7": -3.277, 64 | "42.9": -3.606, 65 | "50.0": -3.69, 66 | "57.1": -3.561, 67 | "64.3": -3.248, 68 | "71.4": -2.782, 69 | "78.6": -2.193, 70 | "85.7": -1.513, 71 | "92.9": -0.772, 72 | "100.0": 0 73 | } 74 | }, 75 | "displacement_z": { 76 | "1": { 77 | "0.0": 0, 78 | "7.1": 0, 79 | "14.3": 0, 80 | "21.4": 0, 81 | "28.6": 0, 82 | "30.0": 0, 83 | "35.7": 0, 84 | "42.9": 0, 85 | "50.0": 0, 86 | "57.1": 0, 87 | "64.3": 0, 88 | "71.4": 0, 89 | "78.6": 0, 90 | "85.7": 0, 91 | "92.9": 0, 92 | "100.0": 0 93 | } 94 | }, 95 | "displacement_sum": { 96 | "1": { 97 | "0.0": 0, 98 | "7.1": 0.278, 99 | "14.3": 0.963, 100 | "21.4": 1.835, 101 | "28.6": 2.673, 102 | "30.0": 2.817, 103 | "35.7": 3.277, 104 | "42.9": 3.606, 105 | "50.0": 3.69, 106 | "57.1": 3.561, 107 | "64.3": 3.248, 108 | "71.4": 2.782, 109 | "78.6": 2.193, 110 | "85.7": 1.513, 111 | "92.9": 0.772, 112 | "100.0": 0 113 | } 114 | }, 115 | "displacement_local_x": { 116 | "1": { 117 | "0.0": 0, 118 | "7.1": 0, 119 | "14.3": 0, 120 | "21.4": 0, 121 | "28.6": 0, 122 | "30.0": 0, 123 | "35.7": 0, 124 | "42.9": 0, 125 | "50.0": 0, 126 | "57.1": 0, 127 | "64.3": 0, 128 | "71.4": 0, 129 | "78.6": 0, 130 | "85.7": 0, 131 | "92.9": 0, 132 | "100.0": 0 133 | } 134 | }, 135 | "displacement_local_y": { 136 | "1": { 137 | "0.0": 0, 138 | "7.1": -0.278, 139 | "14.3": -0.963, 140 | "21.4": -1.835, 141 | "28.6": -2.673, 142 | "30.0": -2.817, 143 | "35.7": -3.277, 144 | "42.9": -3.606, 145 | "50.0": -3.69, 146 | "57.1": -3.561, 147 | "64.3": -3.248, 148 | "71.4": -2.782, 149 | "78.6": -2.193, 150 | "85.7": -1.513, 151 | "92.9": -0.772, 152 | "100.0": 0 153 | } 154 | }, 155 | "displacement_local_z": { 156 | "1": { 157 | "0.0": 0, 158 | "7.1": 0, 159 | "14.3": 0, 160 | "21.4": 0, 161 | "28.6": 0, 162 | "30.0": 0, 163 | "35.7": 0, 164 | "42.9": 0, 165 | "50.0": 0, 166 | "57.1": 0, 167 | "64.3": 0, 168 | "71.4": 0, 169 | "78.6": 0, 170 | "85.7": 0, 171 | "92.9": 0, 172 | "100.0": 0 173 | } 174 | }, 175 | "displacement_local_sum": { 176 | "1": { 177 | "0.0": 0, 178 | "7.1": 0.278, 179 | "14.3": 0.963, 180 | "21.4": 1.835, 181 | "28.6": 2.673, 182 | "30.0": 2.817, 183 | "35.7": 3.277, 184 | "42.9": 3.606, 185 | "50.0": 3.69, 186 | "57.1": 3.561, 187 | "64.3": 3.248, 188 | "71.4": 2.782, 189 | "78.6": 2.193, 190 | "85.7": 1.513, 191 | "92.9": 0.772, 192 | "100.0": 0 193 | } 194 | }, 195 | "rotation_x": { 196 | "1": { 197 | "0.0": 0, 198 | "7.1": 0, 199 | "14.3": 0, 200 | "21.4": 0, 201 | "28.6": 0, 202 | "30.0": 0, 203 | "35.7": 0, 204 | "42.9": 0, 205 | "50.0": 0, 206 | "57.1": 0, 207 | "64.3": 0, 208 | "71.4": 0, 209 | "78.6": 0, 210 | "85.7": 0, 211 | "92.9": 0, 212 | "100.0": 0 213 | } 214 | }, 215 | "rotation_y": { 216 | "1": { 217 | "0.0": 0, 218 | "7.1": 0, 219 | "14.3": 0, 220 | "21.4": 0, 221 | "28.6": 0, 222 | "30.0": 0, 223 | "35.7": 0, 224 | "42.9": 0, 225 | "50.0": 0, 226 | "57.1": 0, 227 | "64.3": 0, 228 | "71.4": 0, 229 | "78.6": 0, 230 | "85.7": 0, 231 | "92.9": 0, 232 | "100.0": 0 233 | } 234 | }, 235 | "rotation_z": { 236 | "1": { 237 | "0.0": 0, 238 | "7.1": -0.001, 239 | "14.3": -0.002, 240 | "21.4": -0.002, 241 | "28.6": -0.002, 242 | "30.0": -0.002, 243 | "35.7": -0.001, 244 | "42.9": -0.001, 245 | "50.0": 0, 246 | "57.1": 0.001, 247 | "64.3": 0.001, 248 | "71.4": 0.001, 249 | "78.6": 0.002, 250 | "85.7": 0.002, 251 | "92.9": 0.002, 252 | "100.0": 0.002 253 | } 254 | }, 255 | "rotation_local_x": { 256 | "1": { 257 | "0.0": 0, 258 | "7.1": 0, 259 | "14.3": 0, 260 | "21.4": 0, 261 | "28.6": 0, 262 | "30.0": 0, 263 | "35.7": 0, 264 | "42.9": 0, 265 | "50.0": 0, 266 | "57.1": 0, 267 | "64.3": 0, 268 | "71.4": 0, 269 | "78.6": 0, 270 | "85.7": 0, 271 | "92.9": 0, 272 | "100.0": 0 273 | } 274 | }, 275 | "rotation_local_y": { 276 | "1": { 277 | "0.0": 0, 278 | "7.1": 0, 279 | "14.3": 0, 280 | "21.4": 0, 281 | "28.6": 0, 282 | "30.0": 0, 283 | "35.7": 0, 284 | "42.9": 0, 285 | "50.0": 0, 286 | "57.1": 0, 287 | "64.3": 0, 288 | "71.4": 0, 289 | "78.6": 0, 290 | "85.7": 0, 291 | "92.9": 0, 292 | "100.0": 0 293 | } 294 | }, 295 | "rotation_local_z": { 296 | "1": { 297 | "0.0": 0, 298 | "7.1": -0.001, 299 | "14.3": -0.002, 300 | "21.4": -0.002, 301 | "28.6": -0.002, 302 | "30.0": -0.002, 303 | "35.7": -0.001, 304 | "42.9": -0.001, 305 | "50.0": 0, 306 | "57.1": 0.001, 307 | "64.3": 0.001, 308 | "71.4": 0.001, 309 | "78.6": 0.002, 310 | "85.7": 0.002, 311 | "92.9": 0.002, 312 | "100.0": 0.002 313 | } 314 | } 315 | }, 316 | "member_forces": { 317 | "axial_force": { 318 | "1": { 319 | "0.0": 0, 320 | "7.1": 0, 321 | "14.3": 0, 322 | "21.4": 0, 323 | "28.6": 0, 324 | "30.0": 0, 325 | "35.7": 0, 326 | "42.9": 0, 327 | "50.0": 0, 328 | "57.1": 0, 329 | "64.3": 0, 330 | "71.4": 0, 331 | "78.6": 0, 332 | "85.7": 0, 333 | "92.9": 0, 334 | "100.0": 0 335 | } 336 | }, 337 | "shear_force_y": { 338 | "1": { 339 | "0.0": 8.785, 340 | "7.1": 8.785, 341 | "14.3": 8.785, 342 | "21.4": 8.785, 343 | "28.6": 8.785, 344 | "30.0": [8.785, -1.215], 345 | "35.7": -1.215, 346 | "42.9": -1.215, 347 | "50.0": -1.215, 348 | "57.1": -1.215, 349 | "64.3": -1.215, 350 | "71.4": -1.215, 351 | "78.6": -1.215, 352 | "85.7": -1.215, 353 | "92.9": -1.215, 354 | "100.0": -1.215 355 | } 356 | }, 357 | "shear_force_z": { 358 | "1": { 359 | "0.0": 0, 360 | "7.1": 0, 361 | "14.3": 0, 362 | "21.4": 0, 363 | "28.6": 0, 364 | "30.0": 0, 365 | "35.7": 0, 366 | "42.9": 0, 367 | "50.0": 0, 368 | "57.1": 0, 369 | "64.3": 0, 370 | "71.4": 0, 371 | "78.6": 0, 372 | "85.7": 0, 373 | "92.9": 0, 374 | "100.0": 0 375 | } 376 | }, 377 | "bending_moment_y": { 378 | "1": { 379 | "0.0": 0, 380 | "7.1": 0, 381 | "14.3": 0, 382 | "21.4": 0, 383 | "28.6": 0, 384 | "30.0": 0, 385 | "35.7": 0, 386 | "42.9": 0, 387 | "50.0": 0, 388 | "57.1": 0, 389 | "64.3": 0, 390 | "71.4": 0, 391 | "78.6": 0, 392 | "85.7": 0, 393 | "92.9": 0, 394 | "100.0": 0 395 | } 396 | }, 397 | "bending_moment_z": { 398 | "1": { 399 | "0.0": -8.925, 400 | "7.1": -5.787, 401 | "14.3": -2.65, 402 | "21.4": 0.487, 403 | "28.6": 3.625, 404 | "30.0": 4.253, 405 | "35.7": 3.905, 406 | "42.9": 3.471, 407 | "50.0": 3.038, 408 | "57.1": 2.604, 409 | "64.3": 2.17, 410 | "71.4": 1.736, 411 | "78.6": 1.302, 412 | "85.7": 0.868, 413 | "92.9": 0.434, 414 | "100.0": 0 415 | } 416 | }, 417 | "torsion": { 418 | "1": { 419 | "0.0": 0, 420 | "7.1": 0, 421 | "14.3": 0, 422 | "21.4": 0, 423 | "28.6": 0, 424 | "30.0": 0, 425 | "35.7": 0, 426 | "42.9": 0, 427 | "50.0": 0, 428 | "57.1": 0, 429 | "64.3": 0, 430 | "71.4": 0, 431 | "78.6": 0, 432 | "85.7": 0, 433 | "92.9": 0, 434 | "100.0": 0 435 | } 436 | } 437 | }, 438 | "member_stresses": { 439 | "axial_stress": { 440 | "1": { 441 | "0.0": 0, 442 | "7.1": 0, 443 | "14.3": 0, 444 | "21.4": 0, 445 | "28.6": 0, 446 | "30.0": 0, 447 | "35.7": 0, 448 | "42.9": 0, 449 | "50.0": 0, 450 | "57.1": 0, 451 | "64.3": 0, 452 | "71.4": 0, 453 | "78.6": 0, 454 | "85.7": 0, 455 | "92.9": 0, 456 | "100.0": 0 457 | } 458 | }, 459 | "top_bending_stress_z": { 460 | "1": { 461 | "0.0": -76.43, 462 | "7.1": -49.561, 463 | "14.3": -22.693, 464 | "21.4": 4.175, 465 | "28.6": 31.043, 466 | "30.0": 36.416, 467 | "35.7": 33.444, 468 | "42.9": 29.728, 469 | "50.0": 26.012, 470 | "57.1": 22.296, 471 | "64.3": 18.58, 472 | "71.4": 14.864, 473 | "78.6": 11.148, 474 | "85.7": 7.432, 475 | "92.9": 3.716, 476 | "100.0": 0 477 | } 478 | }, 479 | "top_bending_stress_y": { 480 | "1": { 481 | "0.0": 0, 482 | "7.1": 0, 483 | "14.3": 0, 484 | "21.4": 0, 485 | "28.6": 0, 486 | "30.0": 0, 487 | "35.7": 0, 488 | "42.9": 0, 489 | "50.0": 0, 490 | "57.1": 0, 491 | "64.3": 0, 492 | "71.4": 0, 493 | "78.6": 0, 494 | "85.7": 0, 495 | "92.9": 0, 496 | "100.0": 0 497 | } 498 | }, 499 | "btm_bending_stress_z": { 500 | "1": { 501 | "0.0": 76.43, 502 | "7.1": 49.561, 503 | "14.3": 22.693, 504 | "21.4": -4.175, 505 | "28.6": -31.043, 506 | "30.0": -36.416, 507 | "35.7": -33.444, 508 | "42.9": -29.728, 509 | "50.0": -26.012, 510 | "57.1": -22.296, 511 | "64.3": -18.58, 512 | "71.4": -14.864, 513 | "78.6": -11.148, 514 | "85.7": -7.432, 515 | "92.9": -3.716, 516 | "100.0": 0 517 | } 518 | }, 519 | "btm_bending_stress_y": { 520 | "1": { 521 | "0.0": 0, 522 | "7.1": 0, 523 | "14.3": 0, 524 | "21.4": 0, 525 | "28.6": 0, 526 | "30.0": 0, 527 | "35.7": 0, 528 | "42.9": 0, 529 | "50.0": 0, 530 | "57.1": 0, 531 | "64.3": 0, 532 | "71.4": 0, 533 | "78.6": 0, 534 | "85.7": 0, 535 | "92.9": 0, 536 | "100.0": 0 537 | } 538 | }, 539 | "shear_stress_z": { 540 | "1": { 541 | "0.0": 0, 542 | "7.1": 0, 543 | "14.3": 0, 544 | "21.4": 0, 545 | "28.6": 0, 546 | "30.0": 0, 547 | "35.7": 0, 548 | "42.9": 0, 549 | "50.0": 0, 550 | "57.1": 0, 551 | "64.3": 0, 552 | "71.4": 0, 553 | "78.6": 0, 554 | "85.7": 0, 555 | "92.9": 0, 556 | "100.0": 0 557 | } 558 | }, 559 | "shear_stress_y": { 560 | "1": { 561 | "0.0": 9.792, 562 | "7.1": 9.792, 563 | "14.3": 9.792, 564 | "21.4": 9.792, 565 | "28.6": 9.792, 566 | "30.0": [9.792, -1.354], 567 | "35.7": -1.354, 568 | "42.9": -1.354, 569 | "50.0": -1.354, 570 | "57.1": -1.354, 571 | "64.3": -1.354, 572 | "71.4": -1.354, 573 | "78.6": -1.354, 574 | "85.7": -1.354, 575 | "92.9": -1.354, 576 | "100.0": -1.354 577 | } 578 | }, 579 | "torsion_stress": { 580 | "1": { 581 | "0.0": 0, 582 | "7.1": 0, 583 | "14.3": 0, 584 | "21.4": 0, 585 | "28.6": 0, 586 | "30.0": 0, 587 | "35.7": 0, 588 | "42.9": 0, 589 | "50.0": 0, 590 | "57.1": 0, 591 | "64.3": 0, 592 | "71.4": 0, 593 | "78.6": 0, 594 | "85.7": 0, 595 | "92.9": 0, 596 | "100.0": 0 597 | } 598 | }, 599 | "top_combined_stress_z": { 600 | "1": { 601 | "0.0": -76.43, 602 | "7.1": -49.561, 603 | "14.3": -22.693, 604 | "21.4": 4.175, 605 | "28.6": 31.043, 606 | "30.0": 36.416, 607 | "35.7": 33.444, 608 | "42.9": 29.728, 609 | "50.0": 26.012, 610 | "57.1": 22.296, 611 | "64.3": 18.58, 612 | "71.4": 14.864, 613 | "78.6": 11.148, 614 | "85.7": 7.432, 615 | "92.9": 3.716, 616 | "100.0": 0 617 | } 618 | }, 619 | "top_combined_stress_y": { 620 | "1": { 621 | "0.0": 0, 622 | "7.1": 0, 623 | "14.3": 0, 624 | "21.4": 0, 625 | "28.6": 0, 626 | "30.0": 0, 627 | "35.7": 0, 628 | "42.9": 0, 629 | "50.0": 0, 630 | "57.1": 0, 631 | "64.3": 0, 632 | "71.4": 0, 633 | "78.6": 0, 634 | "85.7": 0, 635 | "92.9": 0, 636 | "100.0": 0 637 | } 638 | }, 639 | "btm_combined_stress_z": { 640 | "1": { 641 | "0.0": 76.43, 642 | "7.1": 49.561, 643 | "14.3": 22.693, 644 | "21.4": -4.175, 645 | "28.6": -31.043, 646 | "30.0": -36.416, 647 | "35.7": -33.444, 648 | "42.9": -29.728, 649 | "50.0": -26.012, 650 | "57.1": -22.296, 651 | "64.3": -18.58, 652 | "71.4": -14.864, 653 | "78.6": -11.148, 654 | "85.7": -7.432, 655 | "92.9": -3.716, 656 | "100.0": 0 657 | } 658 | }, 659 | "btm_combined_stress_y": { 660 | "1": { 661 | "0.0": 0, 662 | "7.1": 0, 663 | "14.3": 0, 664 | "21.4": 0, 665 | "28.6": 0, 666 | "30.0": 0, 667 | "35.7": 0, 668 | "42.9": 0, 669 | "50.0": 0, 670 | "57.1": 0, 671 | "64.3": 0, 672 | "71.4": 0, 673 | "78.6": 0, 674 | "85.7": 0, 675 | "92.9": 0, 676 | "100.0": 0 677 | } 678 | } 679 | }, 680 | "member_lengths": { "1": 5 }, 681 | "member_stations": { 682 | "1": [ 683 | 0, 684 | 7.142857142857143, 685 | 14.285714285714286, 686 | 21.428571428571427, 687 | 28.571428571428573, 688 | 30, 689 | 35.714285714285715, 690 | 42.857142857142854, 691 | 50, 692 | 57.142857142857146, 693 | 64.28571428571429, 694 | 71.42857142857143, 695 | 78.57142857142857, 696 | 85.71428571428571, 697 | 92.85714285714286, 698 | 100 699 | ] 700 | }, 701 | "member_discontinuities": { "1": 1 }, 702 | "member_minimums": { 703 | "displacement_x": { "1": 0 }, 704 | "displacement_y": { "1": -3.69043508 }, 705 | "displacement_z": { "1": 0 }, 706 | "displacement_sum": { "1": 0 }, 707 | "displacement_local_x": { "1": 0 }, 708 | "displacement_local_y": { "1": -3.69043508 }, 709 | "displacement_local_z": { "1": 0 }, 710 | "displacement_local_sum": { "1": 0 }, 711 | "displacement_relative": { "1": 0 }, 712 | "displacement_relative_local_x": { "1": 0 }, 713 | "displacement_relative_local_y": { "1": -3.69043508 }, 714 | "displacement_relative_local_z": { "1": 0 }, 715 | "displacement_span_ratio": { "1": 1354 }, 716 | "displacement_span_ratio_2": { "1": 1354 }, 717 | "rotation_x": { "1": 0 }, 718 | "rotation_y": { "1": 0 }, 719 | "rotation_z": { "1": -0.0024972869 }, 720 | "rotation_local_x": { "1": 0 }, 721 | "rotation_local_y": { "1": 0 }, 722 | "rotation_local_z": { "1": -0.0024972869 }, 723 | "axial_force": { "1": 0 }, 724 | "shear_force_y": { "1": -1.215 }, 725 | "shear_force_z": { "1": 0 }, 726 | "torsion": { "1": 0 }, 727 | "bending_moment_y": { "1": 0 }, 728 | "bending_moment_z": { "1": -8.925 }, 729 | "top_bending_stress_z": { "1": -76.42955801 }, 730 | "top_bending_stress_y": { "1": 0 }, 731 | "btm_bending_stress_z": { "1": -36.41643646 }, 732 | "btm_bending_stress_y": { "1": 0 }, 733 | "shear_stress_z": { "1": 0 }, 734 | "shear_stress_y": { "1": -1.35430098 }, 735 | "axial_stress": { "1": 0 }, 736 | "top_combined_stress_z": { "1": -76.42955801 }, 737 | "top_combined_stress_y": { "1": 0 }, 738 | "btm_combined_stress_z": { "1": -36.41643646 }, 739 | "btm_combined_stress_y": { "1": 0 }, 740 | "torsion_stress": { "1": 0 } 741 | }, 742 | "member_maximums": { 743 | "displacement_x": { "1": 0 }, 744 | "displacement_y": { "1": 0 }, 745 | "displacement_z": { "1": 0 }, 746 | "displacement_sum": { "1": 3.69043508 }, 747 | "displacement_local_x": { "1": 0 }, 748 | "displacement_local_y": { "1": 0 }, 749 | "displacement_local_z": { "1": 0 }, 750 | "displacement_local_sum": { "1": 3.69043508 }, 751 | "displacement_relative": { "1": 3.69043508 }, 752 | "displacement_relative_local_x": { "1": 0 }, 753 | "displacement_relative_local_y": { "1": 0 }, 754 | "displacement_relative_local_z": { "1": 0 }, 755 | "displacement_span_ratio": { "1": 1000000000000 }, 756 | "displacement_span_ratio_2": { "1": 1354 }, 757 | "rotation_x": { "1": 0 }, 758 | "rotation_y": { "1": 0 }, 759 | "rotation_z": { "1": 0.0021754144 }, 760 | "rotation_local_x": { "1": 0 }, 761 | "rotation_local_y": { "1": 0 }, 762 | "rotation_local_z": { "1": 0.0021754144 }, 763 | "axial_force": { "1": 0 }, 764 | "shear_force_y": { "1": 8.785 }, 765 | "shear_force_z": { "1": 0 }, 766 | "torsion": { "1": 0 }, 767 | "bending_moment_y": { "1": 0 }, 768 | "bending_moment_z": { "1": 4.2525 }, 769 | "top_bending_stress_z": { "1": 36.41643646 }, 770 | "top_bending_stress_y": { "1": 0 }, 771 | "btm_bending_stress_z": { "1": 76.42955801 }, 772 | "btm_bending_stress_y": { "1": 0 }, 773 | "shear_stress_z": { "1": 0 }, 774 | "shear_stress_y": { "1": 9.79220912 }, 775 | "axial_stress": { "1": 0 }, 776 | "top_combined_stress_z": { "1": 36.41643646 }, 777 | "top_combined_stress_y": { "1": 0 }, 778 | "btm_combined_stress_z": { "1": 76.42955801 }, 779 | "btm_combined_stress_y": { "1": 0 }, 780 | "torsion_stress": { "1": 0 } 781 | }, 782 | "member_peak_results": { 783 | "displacement_x": { "min": 0, "max": 0 }, 784 | "displacement_y": { "min": -3.69043508, "max": 0 }, 785 | "displacement_z": { "min": 0, "max": 0 }, 786 | "displacement_sum": { "min": 0, "max": 3.69043508 }, 787 | "displacement_local_x": { "min": 0, "max": 0 }, 788 | "displacement_local_y": { "min": -3.69043508, "max": 0 }, 789 | "displacement_local_z": { "min": 0, "max": 0 }, 790 | "displacement_local_sum": { "min": 0, "max": 3.69043508 }, 791 | "displacement_relative": { "min": 0, "max": 3.69043508 }, 792 | "displacement_relative_local_x": { "min": 0, "max": 0 }, 793 | "displacement_relative_local_y": { "min": -3.69043508, "max": 0 }, 794 | "displacement_relative_local_z": { "min": 0, "max": 0 }, 795 | "displacement_span_ratio": { "min": 1354, "max": 1000000000000 }, 796 | "displacement_span_ratio_2": { "min": 1354, "max": 1354 }, 797 | "rotation_x": { "min": 0, "max": 0 }, 798 | "rotation_y": { "min": 0, "max": 0 }, 799 | "rotation_z": { "min": -0.0024972869, "max": 0.0021754144 }, 800 | "rotation_local_x": { "min": 0, "max": 0 }, 801 | "rotation_local_y": { "min": 0, "max": 0 }, 802 | "rotation_local_z": { "min": -0.0024972869, "max": 0.0021754144 }, 803 | "axial_force": { "min": 0, "max": 0 }, 804 | "shear_force_y": { "min": -1.215, "max": 8.785 }, 805 | "shear_force_z": { "min": 0, "max": 0 }, 806 | "torsion": { "min": 0, "max": 0 }, 807 | "bending_moment_y": { "min": 0, "max": 0 }, 808 | "bending_moment_z": { "min": -8.925, "max": 4.2525 }, 809 | "top_bending_stress_z": { "min": -76.42955801, "max": 36.41643646 }, 810 | "top_bending_stress_y": { "min": 0, "max": 0 }, 811 | "btm_bending_stress_z": { "min": -36.41643646, "max": 76.42955801 }, 812 | "btm_bending_stress_y": { "min": 0, "max": 0 }, 813 | "shear_stress_z": { "min": 0, "max": 0 }, 814 | "shear_stress_y": { "min": -1.35430098, "max": 9.79220912 }, 815 | "axial_stress": { "min": 0, "max": 0 }, 816 | "top_combined_stress_z": { "min": -76.42955801, "max": 36.41643646 }, 817 | "top_combined_stress_y": { "min": 0, "max": 0 }, 818 | "btm_combined_stress_z": { "min": -36.41643646, "max": 76.42955801 }, 819 | "btm_combined_stress_y": { "min": 0, "max": 0 }, 820 | "torsion_stress": { "min": 0, "max": 0 } 821 | }, 822 | "plate_displacements": { 823 | "displacement_x": {}, 824 | "displacement_y": {}, 825 | "displacement_z": {}, 826 | "displacement_sum": {} 827 | }, 828 | "plate_forces": { 829 | "force_x": {}, 830 | "force_xy": {}, 831 | "force_xz": {}, 832 | "force_y": {}, 833 | "force_yz": {}, 834 | "moment_x": {}, 835 | "moment_xy": {}, 836 | "moment_y": {} 837 | }, 838 | "plate_stresses": { 839 | "stress_major_principal_top": {}, 840 | "stress_max_shear_top": {}, 841 | "stress_minor_principal_top": {}, 842 | "stress_von_mises_top": {}, 843 | "stress_xx_top": {}, 844 | "stress_yy_top": {}, 845 | "stress_xy_top": {}, 846 | "stress_major_principal_btm": {}, 847 | "stress_max_shear_btm": {}, 848 | "stress_minor_principal_btm": {}, 849 | "stress_von_mises_btm": {}, 850 | "stress_xx_btm": {}, 851 | "stress_yy_btm": {}, 852 | "stress_xy_btm": {} 853 | }, 854 | "plate_minimums": {}, 855 | "plate_maximums": {}, 856 | "plate_peak_results": { 857 | "displacement_x": { "min": 0, "max": 0 }, 858 | "displacement_y": { "min": 0, "max": 0 }, 859 | "displacement_z": { "min": 0, "max": 0 }, 860 | "displacement_sum": { "min": 0, "max": 0 }, 861 | "stress_xx_top": { "min": 0, "max": 0 }, 862 | "stress_xx_btm": { "min": 0, "max": 0 }, 863 | "stress_yy_top": { "min": 0, "max": 0 }, 864 | "stress_yy_btm": { "min": 0, "max": 0 }, 865 | "stress_xy_top": { "min": 0, "max": 0 }, 866 | "stress_xy_btm": { "min": 0, "max": 0 }, 867 | "stress_major_principal_top": { "min": 0, "max": 0 }, 868 | "stress_major_principal_btm": { "min": 0, "max": 0 }, 869 | "stress_minor_principal_top": { "min": 0, "max": 0 }, 870 | "stress_minor_principal_btm": { "min": 0, "max": 0 }, 871 | "stress_von_mises_top": { "min": 0, "max": 0 }, 872 | "stress_von_mises_btm": { "min": 0, "max": 0 }, 873 | "stress_max_shear_top": { "min": 0, "max": 0 }, 874 | "stress_max_shear_btm": { "min": 0, "max": 0 }, 875 | "force_x": { "min": 0, "max": 0 }, 876 | "force_y": { "min": 0, "max": 0 }, 877 | "force_xy": { "min": 0, "max": 0 }, 878 | "force_xz": { "min": 0, "max": 0 }, 879 | "force_yz": { "min": 0, "max": 0 }, 880 | "moment_x": { "min": 0, "max": 0 }, 881 | "moment_y": { "min": 0, "max": 0 }, 882 | "moment_xy": { "min": 0, "max": 0 } 883 | }, 884 | "buckling": "disabled", 885 | "dynamic_frequency": "disabled" 886 | } 887 | }, 888 | "msg": "Solved Successfully!", 889 | "comments": " Linear Static Analysis Completed ", 890 | "status": 0, 891 | "function": "S3D.model.solve" 892 | }, 893 | { 894 | "data": { 895 | "capacity": { 896 | "axial_tension": { "1": 538.2 }, 897 | "axial_compression": { "1": 538.2 }, 898 | "moment_z": { "1": 31.590000000000003 }, 899 | "moment_y": { "1": 6.289919999999986 }, 900 | "shear_y": { "1": 130.572 }, 901 | "shear_z": { "1": 200.07 }, 902 | "axial_buckling": { "1": 68.36937702415861 }, 903 | "flexure_buckling": { "1": 11.498996211214772 } 904 | }, 905 | "ratio": { 906 | "axial": { "1": 0 }, 907 | "moment_z": { "1": 0.2825261158594492 }, 908 | "moment_y": { "1": 0 }, 909 | "shear_y": { "1": 0.0672808871733603 }, 910 | "shear_z": { "1": 0 }, 911 | "buckling_compression": { "1": 0 }, 912 | "buckling_bending": { "1": 0.7761547039467326 }, 913 | "combined_strength": { "1": 0.2825261158594492 }, 914 | "combined_buckling": { "1": 0.7761547039467326 }, 915 | "slender": { "1": 0.7800420555749596 }, 916 | "worstlc": { "1": "#1" }, 917 | "displacement": { "1": 0.18452200000000002 } 918 | }, 919 | "html_summary_link": "https://solver.skyciv.com/temp/view_report_tTrMlmD9cYBuyfdK.php", 920 | "html_download_link": "https://solver.skyciv.com/temp/download_html_report_tTrMlmD9cYBuyfdK.php", 921 | "pdf_download_link": "https://solver.skyciv.com/temp/download_report_tTrMlmD9cYBuyfdK.php", 922 | "reports": { 923 | "1": { 924 | "html_view_link": "https://solver.skyciv.com/temp/view_report_tTrMlmD9cYBuyfdK_0.php", 925 | "html_download_link": "https://solver.skyciv.com/temp/download_html_report_tTrMlmD9cYBuyfdK_0.php", 926 | "pdf_download_link": "https://solver.skyciv.com/temp/download_report_tTrMlmD9cYBuyfdK_0.php" 927 | } 928 | }, 929 | "summary": { 930 | "failed_members": [], 931 | "passed_members": ["1"], 932 | "critical": { 933 | "utility_ratio": 0.7800420555749596, 934 | "member_id": "1", 935 | "action": "slender", 936 | "load_case": "#1", 937 | "status": "PASS" 938 | } 939 | } 940 | }, 941 | "msg": "Member Design check for AS_4100-1998 was run successfully.", 942 | "status": 0, 943 | "function": "S3D.design.member.check" 944 | }, 945 | { 946 | "data": "https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 947 | "msg": "Model was successfully saved to your SkyCiv cloud storage in the folder api/intro-to-programming/. You can access this file from your SkyCiv Dashboard, or directly from https://platform.skyciv.com/structural?preload_name=simple-beam-test&preload_path=api/intro-to-programming/", 948 | "status": 0, 949 | "function": "S3D.file.save" 950 | } 951 | ] 952 | } 953 | --------------------------------------------------------------------------------