Full Code of xamarin/Workbooks for AI

master 630fae550140 cached
657 files
4.9 MB
1.3M tokens
206 symbols
1 requests
Download .txt
Showing preview only (5,294K chars total). Download the full file or copy to clipboard to get everything.
Repository: xamarin/Workbooks
Branch: master
Commit: 630fae550140
Files: 657
Total size: 4.9 MB

Directory structure:
gitextract_k3w_f6vi/

├── .gitignore
├── LICENSE.md
├── README.md
├── SDK/
│   ├── .gitignore
│   ├── README.md
│   ├── Samples/
│   │   ├── KitchenSink/
│   │   │   ├── AgentIntegration.cs
│   │   │   ├── Api.cs
│   │   │   ├── KitchenSink.workbook
│   │   │   ├── KitchenSinkIntegration.csproj
│   │   │   ├── KitchenSinkIntegration.js
│   │   │   ├── KitchenSinkIntegration.sln
│   │   │   └── Person.cs
│   │   └── XamarinInteractive.targets
│   └── typings/
│       └── xamarin-interactive.d.ts
├── android/
│   ├── README.md
│   ├── getting-started/
│   │   ├── AndroidAppBasics.workbook
│   │   ├── hello-android-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── user-interface/
│       ├── 2D-drawing.workbook
│       ├── AutoCompleteTextView.workbook
│       ├── PropertyAnimation.workbook
│       ├── listview.workbook
│       ├── meta.json
│       ├── popupmenus.workbook
│       ├── spinner.workbook
│       ├── switch.workbook
│       └── views.workbook
├── azure/
│   ├── cogs/
│   │   ├── emotion.workbook/
│   │   │   ├── employees.csx
│   │   │   └── index.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── tryazure/
│       ├── TryAzure-Mac.workbook
│       ├── TryAzure-WPF.workbook
│       ├── TryAzure-iOS.workbook
│       └── meta.json
├── charts/
│   ├── meta.json
│   ├── oxyplot/
│   │   ├── OxyPlot.workbook
│   │   └── meta.json
│   └── xplot/
│       ├── XPlot.workbook
│       └── meta.json
├── csharp/
│   ├── async/
│   │   ├── README.md
│   │   ├── async-await-wpf.workbook
│   │   ├── async-await.workbook
│   │   └── meta.json
│   ├── collections/
│   │   ├── README.md
│   │   ├── arrays.workbook
│   │   └── meta.json
│   ├── csharp6/
│   │   ├── README.md
│   │   ├── csharp6.workbook
│   │   └── meta.json
│   ├── csharp7/
│   │   ├── csharp7.workbook
│   │   ├── index.workbook
│   │   └── meta.json
│   ├── linq/
│   │   ├── 101-linq-examples.workbook/
│   │   │   ├── 101_Linq_Examples.csx
│   │   │   ├── Customers.xml
│   │   │   └── index.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── roslyn/
│       ├── meta.json
│       └── roslyn-syntax-trees.workbook/
│           └── index.workbook
├── graphics/
│   ├── meta.json
│   ├── skiasharp/
│   │   ├── colors/
│   │   │   └── colors.workbook/
│   │   │       └── index.workbook
│   │   ├── images/
│   │   │   └── images.workbook/
│   │   │       └── index.workbook
│   │   ├── introduction/
│   │   │   └── introduction.workbook/
│   │   │       └── index.workbook
│   │   ├── logo/
│   │   │   └── skialogo-ios.workbook/
│   │   │       └── index.workbook
│   │   ├── meta.json
│   │   └── pixmap/
│   │       └── pixmap.workbook/
│   │           └── index.workbook
│   ├── tiny-renderer/
│   │   ├── README.md
│   │   ├── Renderer/
│   │   │   ├── Listings/
│   │   │   │   ├── ListingTexture.cs
│   │   │   │   └── ListingZBuffer.cs
│   │   │   ├── Program.cs
│   │   │   ├── Properties/
│   │   │   │   └── AssemblyInfo.cs
│   │   │   ├── Renderer.csproj
│   │   │   ├── Renderer.sln
│   │   │   ├── Tests/
│   │   │   │   ├── GouraudShaderFixture.cs
│   │   │   │   ├── MatrixFixture.cs
│   │   │   │   ├── ModelFixture.cs
│   │   │   │   └── VectorFixture.cs
│   │   │   ├── WorkbookItems/
│   │   │   │   ├── Geometry.cs
│   │   │   │   ├── Image.cs
│   │   │   │   ├── Matrix.cs
│   │   │   │   ├── Model.cs
│   │   │   │   ├── Shaders.cs
│   │   │   │   └── Utils.cs
│   │   │   └── packages.config
│   │   ├── lesson1.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   └── obj/
│   │   │       └── african_head.obj
│   │   ├── lesson2.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   └── obj/
│   │   │       └── african_head.obj
│   │   ├── lesson3.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       └── african_head_spec.tga
│   │   ├── lesson4.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   └── obj/
│   │   │       └── cube.obj
│   │   ├── lesson5.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       └── african_head_spec.tga
│   │   ├── lesson6.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       ├── african_head_spec.tga
│   │   │       ├── diablo3-total-occlusion.tga
│   │   │       ├── diablo3_pose.obj
│   │   │       ├── diablo3_pose_diffuse.tga
│   │   │       ├── diablo3_pose_glow.tga
│   │   │       ├── diablo3_pose_nm.tga
│   │   │       ├── diablo3_pose_nm_tangent.tga
│   │   │       └── diablo3_pose_spec.tga
│   │   ├── lesson6bis.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   ├── lesson6.workbook
│   │   │   ├── lesson6bis.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       └── african_head_spec.tga
│   │   ├── lesson7.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   ├── lesson6.workbook
│   │   │   ├── lesson6bis.csx
│   │   │   ├── lesson6bis.workbook
│   │   │   └── obj/
│   │   │       ├── diablo3-total-occlusion.tga
│   │   │       ├── diablo3_pose.obj
│   │   │       ├── diablo3_pose_diffuse.tga
│   │   │       ├── diablo3_pose_glow.tga
│   │   │       ├── diablo3_pose_nm.tga
│   │   │       ├── diablo3_pose_nm_tangent.tga
│   │   │       └── diablo3_pose_spec.tga
│   │   ├── lesson8.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   ├── lesson6.workbook
│   │   │   ├── lesson6bis.csx
│   │   │   ├── lesson6bis.workbook
│   │   │   ├── lesson7.workbook
│   │   │   └── obj/
│   │   │       ├── diablo3-total-occlusion.tga
│   │   │       ├── diablo3_pose.obj
│   │   │       ├── diablo3_pose_diffuse.tga
│   │   │       ├── diablo3_pose_glow.tga
│   │   │       ├── diablo3_pose_nm.tga
│   │   │       ├── diablo3_pose_nm_tangent.tga
│   │   │       └── diablo3_pose_spec.tga
│   │   └── meta.json
│   └── urhosharp/
│       ├── .gitignore
│       ├── animated-model/
│       │   └── animated-model.workbook/
│       │       ├── Data/
│       │       │   ├── Animations/
│       │       │   │   ├── Mutant_Block_LY.ani
│       │       │   │   ├── Mutant_Death.ani
│       │       │   │   ├── Mutant_HipHop1.ani
│       │       │   │   ├── Mutant_HitHead_LY.ani
│       │       │   │   ├── Mutant_Idle0.ani
│       │       │   │   ├── Mutant_Idle1.ani
│       │       │   │   ├── Mutant_Jump.ani
│       │       │   │   ├── Mutant_Jump1.ani
│       │       │   │   ├── Mutant_JumpAttack.ani
│       │       │   │   ├── Mutant_JumpAttack_RM.ani
│       │       │   │   ├── Mutant_JumpStop.ani
│       │       │   │   ├── Mutant_Kick.ani
│       │       │   │   ├── Mutant_Punch.ani
│       │       │   │   ├── Mutant_Run.ani
│       │       │   │   ├── Mutant_Swipe.ani
│       │       │   │   ├── Mutant_Throw_LY.ani
│       │       │   │   ├── Mutant_Walk.ani
│       │       │   │   └── Mutant_Wave_LY.ani
│       │       │   ├── License.txt
│       │       │   ├── Materials/
│       │       │   │   └── mutant_M.xml
│       │       │   └── Models/
│       │       │       └── Mutant.mdl
│       │       └── index.workbook
│       ├── barchart/
│       │   └── charts.workbook/
│       │       └── index.workbook
│       ├── building-polyhedra/
│       │   └── BuildingPolyhedra.workbook/
│       │       ├── CreateModel.csx
│       │       ├── UrhoSettings.csx
│       │       └── index.workbook
│       ├── circle-of-life/
│       │   └── CircleOfLife.workbook/
│       │       ├── Data/
│       │       │   ├── Materials/
│       │       │   │   └── phong1.xml
│       │       │   └── monkey.mdl
│       │       └── index.workbook
│       ├── compound-shapes/
│       │   └── CreatingUrhoCompoundShapes.workbook/
│       │       └── index.workbook
│       ├── coordinates/
│       │   └── ExploringUrhoCoordinates.workbook/
│       │       └── index.workbook
│       ├── custom-geometries/
│       │   └── CustomGeometries.workbook/
│       │       ├── CreateModel.csx
│       │       └── index.workbook
│       ├── meta.json
│       ├── mobius-strip-speedway/
│       │   └── MobiusStripSpeedway.workbook/
│       │       ├── Data/
│       │       │   ├── BlueRacer/
│       │       │   │   ├── Materials/
│       │       │   │   │   ├── Material1.xml
│       │       │   │   │   ├── White.xml
│       │       │   │   │   ├── White_0.xml
│       │       │   │   │   ├── White_1.xml
│       │       │   │   │   ├── White_10.xml
│       │       │   │   │   ├── White_11.xml
│       │       │   │   │   ├── White_12.xml
│       │       │   │   │   ├── White_13.xml
│       │       │   │   │   ├── White_14.xml
│       │       │   │   │   ├── White_15.xml
│       │       │   │   │   ├── White_16.xml
│       │       │   │   │   ├── White_17.xml
│       │       │   │   │   ├── White_18.xml
│       │       │   │   │   ├── White_19.xml
│       │       │   │   │   ├── White_2.xml
│       │       │   │   │   ├── White_20.xml
│       │       │   │   │   ├── White_21.xml
│       │       │   │   │   ├── White_22.xml
│       │       │   │   │   ├── White_3.xml
│       │       │   │   │   ├── White_4.xml
│       │       │   │   │   ├── White_5.xml
│       │       │   │   │   ├── White_6.xml
│       │       │   │   │   ├── White_7.xml
│       │       │   │   │   ├── White_8.xml
│       │       │   │   │   └── White_9.xml
│       │       │   │   ├── Models/
│       │       │   │   │   ├── Object.1.mdl
│       │       │   │   │   ├── Object.10.mdl
│       │       │   │   │   ├── Object.11.mdl
│       │       │   │   │   ├── Object.12.mdl
│       │       │   │   │   ├── Object.13.mdl
│       │       │   │   │   ├── Object.14.mdl
│       │       │   │   │   ├── Object.15.mdl
│       │       │   │   │   ├── Object.16.mdl
│       │       │   │   │   ├── Object.17.mdl
│       │       │   │   │   ├── Object.18.mdl
│       │       │   │   │   ├── Object.19.mdl
│       │       │   │   │   ├── Object.2.mdl
│       │       │   │   │   ├── Object.20.mdl
│       │       │   │   │   ├── Object.21.mdl
│       │       │   │   │   ├── Object.22.mdl
│       │       │   │   │   ├── Object.23.mdl
│       │       │   │   │   ├── Object.24.mdl
│       │       │   │   │   ├── Object.25.mdl
│       │       │   │   │   ├── Object.26.mdl
│       │       │   │   │   ├── Object.27.mdl
│       │       │   │   │   ├── Object.28.mdl
│       │       │   │   │   ├── Object.29.mdl
│       │       │   │   │   ├── Object.3.mdl
│       │       │   │   │   ├── Object.30.mdl
│       │       │   │   │   ├── Object.31.mdl
│       │       │   │   │   ├── Object.32.mdl
│       │       │   │   │   ├── Object.33.mdl
│       │       │   │   │   ├── Object.34.mdl
│       │       │   │   │   ├── Object.35.mdl
│       │       │   │   │   ├── Object.36.mdl
│       │       │   │   │   ├── Object.37.mdl
│       │       │   │   │   ├── Object.38.mdl
│       │       │   │   │   ├── Object.39.mdl
│       │       │   │   │   ├── Object.4.mdl
│       │       │   │   │   ├── Object.40.mdl
│       │       │   │   │   ├── Object.41.mdl
│       │       │   │   │   ├── Object.42.mdl
│       │       │   │   │   ├── Object.43.mdl
│       │       │   │   │   ├── Object.44.mdl
│       │       │   │   │   ├── Object.45.mdl
│       │       │   │   │   ├── Object.46.mdl
│       │       │   │   │   ├── Object.47.mdl
│       │       │   │   │   ├── Object.48.mdl
│       │       │   │   │   ├── Object.49.mdl
│       │       │   │   │   ├── Object.5.mdl
│       │       │   │   │   ├── Object.50.mdl
│       │       │   │   │   ├── Object.51.mdl
│       │       │   │   │   ├── Object.52.mdl
│       │       │   │   │   ├── Object.53.mdl
│       │       │   │   │   ├── Object.54.mdl
│       │       │   │   │   ├── Object.55.mdl
│       │       │   │   │   ├── Object.56.mdl
│       │       │   │   │   ├── Object.57.mdl
│       │       │   │   │   ├── Object.58.mdl
│       │       │   │   │   ├── Object.59.mdl
│       │       │   │   │   ├── Object.6.mdl
│       │       │   │   │   ├── Object.7.mdl
│       │       │   │   │   ├── Object.8.mdl
│       │       │   │   │   └── Object.9.mdl
│       │       │   │   └── node.xml
│       │       │   └── RedRolls/
│       │       │       ├── Materials/
│       │       │       │   ├── White.xml
│       │       │       │   ├── White_0.xml
│       │       │       │   ├── White_1.xml
│       │       │       │   ├── White_10.xml
│       │       │       │   ├── White_11.xml
│       │       │       │   ├── White_12.xml
│       │       │       │   ├── White_13.xml
│       │       │       │   ├── White_14.xml
│       │       │       │   ├── White_15.xml
│       │       │       │   ├── White_16.xml
│       │       │       │   ├── White_17.xml
│       │       │       │   ├── White_2.xml
│       │       │       │   ├── White_3.xml
│       │       │       │   ├── White_4.xml
│       │       │       │   ├── White_5.xml
│       │       │       │   ├── White_6.xml
│       │       │       │   ├── White_7.xml
│       │       │       │   ├── White_8.xml
│       │       │       │   └── White_9.xml
│       │       │       ├── Models/
│       │       │       │   ├── Object.1.mdl
│       │       │       │   ├── Object.10.mdl
│       │       │       │   ├── Object.11.mdl
│       │       │       │   ├── Object.12.mdl
│       │       │       │   ├── Object.13.mdl
│       │       │       │   ├── Object.14.mdl
│       │       │       │   ├── Object.15.mdl
│       │       │       │   ├── Object.16.mdl
│       │       │       │   ├── Object.17.mdl
│       │       │       │   ├── Object.18.mdl
│       │       │       │   ├── Object.19.mdl
│       │       │       │   ├── Object.2.mdl
│       │       │       │   ├── Object.20.mdl
│       │       │       │   ├── Object.21.mdl
│       │       │       │   ├── Object.22.mdl
│       │       │       │   ├── Object.23.mdl
│       │       │       │   ├── Object.24.mdl
│       │       │       │   ├── Object.25.mdl
│       │       │       │   ├── Object.26.mdl
│       │       │       │   ├── Object.27.mdl
│       │       │       │   ├── Object.28.mdl
│       │       │       │   ├── Object.29.mdl
│       │       │       │   ├── Object.3.mdl
│       │       │       │   ├── Object.30.mdl
│       │       │       │   ├── Object.31.mdl
│       │       │       │   ├── Object.32.mdl
│       │       │       │   ├── Object.33.mdl
│       │       │       │   ├── Object.34.mdl
│       │       │       │   ├── Object.35.mdl
│       │       │       │   ├── Object.36.mdl
│       │       │       │   ├── Object.37.mdl
│       │       │       │   ├── Object.38.mdl
│       │       │       │   ├── Object.39.mdl
│       │       │       │   ├── Object.4.mdl
│       │       │       │   ├── Object.40.mdl
│       │       │       │   ├── Object.41.mdl
│       │       │       │   ├── Object.42.mdl
│       │       │       │   ├── Object.43.mdl
│       │       │       │   ├── Object.44.mdl
│       │       │       │   ├── Object.45.mdl
│       │       │       │   ├── Object.46.mdl
│       │       │       │   ├── Object.47.mdl
│       │       │       │   ├── Object.48.mdl
│       │       │       │   ├── Object.49.mdl
│       │       │       │   ├── Object.5.mdl
│       │       │       │   ├── Object.50.mdl
│       │       │       │   ├── Object.51.mdl
│       │       │       │   ├── Object.52.mdl
│       │       │       │   ├── Object.53.mdl
│       │       │       │   ├── Object.54.mdl
│       │       │       │   ├── Object.55.mdl
│       │       │       │   ├── Object.56.mdl
│       │       │       │   ├── Object.57.mdl
│       │       │       │   ├── Object.58.mdl
│       │       │       │   ├── Object.59.mdl
│       │       │       │   ├── Object.6.mdl
│       │       │       │   ├── Object.60.mdl
│       │       │       │   ├── Object.7.mdl
│       │       │       │   ├── Object.8.mdl
│       │       │       │   └── Object.9.mdl
│       │       │       └── node.xml
│       │       └── index.workbook
│       ├── physics/
│       │   └── physics.workbook/
│       │       ├── Data/
│       │       │   └── bucket.mdl
│       │       └── index.workbook
│       └── planetearth/
│           └── planetearth.workbook/
│               ├── Data/
│               │   ├── Materials/
│               │   │   └── SatNoTexture.xml
│               │   ├── Models/
│               │   │   └── BigSatellite.mdl
│               │   ├── RenderPaths/
│               │   │   └── Outline.xml
│               │   ├── Shaders/
│               │   │   └── GLSL/
│               │   │       └── Outline.glsl
│               │   ├── Techniques/
│               │   │   ├── NoTextureOutline.xml
│               │   │   └── TextureOutline.xml
│               │   └── Textures/
│               │       └── License.txt
│               └── index.workbook
├── ios/
│   ├── README.md
│   ├── getting-started/
│   │   ├── Learning-iOS.workbook
│   │   ├── hello-ios-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   ├── platform-features/
│   │   ├── auto-layout/
│   │   │   └── programmatical-constraints.workbook
│   │   ├── meta.json
│   │   ├── scenekit/
│   │   │   ├── README.md
│   │   │   ├── exploring-scenekit.workbook/
│   │   │   │   └── index.workbook
│   │   │   └── scngeometrysource.workbook/
│   │   │       └── index.workbook
│   │   ├── texttospeech/
│   │   │   └── TextToSpeech.workbook
│   │   ├── touchid/
│   │   │   └── TouchID.workbook
│   │   └── widecolor/
│   │       └── widecolor.workbook/
│   │           └── index.workbook
│   └── user-interface/
│       ├── UIButton/
│       │   └── uibutton.workbook/
│       │       └── index.workbook
│       ├── UIImage/
│       │   └── uiimage.workbook/
│       │       └── index.workbook
│       ├── UILabel/
│       │   └── uilabel.workbook/
│       │       └── index.workbook
│       ├── UINavigationController/
│       │   ├── README.md
│       │   └── uinavigationcontroller.workbook/
│       │       ├── Hierarchical-Navigation.csx
│       │       └── index.workbook
│       ├── UISwitch/
│       │   └── index.workbook
│       ├── UITableView/
│       │   └── uitableview.workbook/
│       │       └── index.workbook
│       ├── alerts/
│       │   └── alert-controller.workbook/
│       │       ├── alert_controller.csx
│       │       └── index.workbook
│       ├── meta.json
│       ├── uitableview-1/
│       │   ├── README.md
│       │   └── uitableview1.workbook/
│       │       └── index.workbook
│       └── web-views/
│           └── web-views.workbook/
│               ├── index.workbook
│               └── tabbar.csx
├── mac/
│   ├── README.md
│   ├── getting-started/
│   │   ├── README.md
│   │   ├── hello-mac-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── user-interface/
│       ├── README.md
│       ├── meta.json
│       ├── outlineview/
│       │   ├── NSOutlineView.workbook
│       │   └── README.md
│       ├── segues/
│       │   ├── README.md
│       │   └── Segues.workbook/
│       │       ├── Main.storyboard
│       │       ├── Main.storyboardc/
│       │       │   ├── 4cK-Eu-ujv-view-YYD-CQ-DLY.nib
│       │       │   ├── CCf-Sq-ZKC-view-E33-5d-PF3.nib
│       │       │   ├── Info.plist
│       │       │   ├── Kgw-Zr-aQ8-view-3jo-us-oYx.nib
│       │       │   ├── MainMenu.nib
│       │       │   ├── NSViewController-CCf-Sq-ZKC.nib
│       │       │   ├── NSViewController-Kgw-Zr-aQ8.nib
│       │       │   ├── NSViewController-hlZ-SX-RFF.nib
│       │       │   ├── NSWindowController-B8D-0N-5wS.nib
│       │       │   ├── NSWindowController-plf-cC-dqu.nib
│       │       │   ├── XdO-WJ-HvK-view-Tof-WT-yQ6.nib
│       │       │   ├── XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
│       │       │   └── hlZ-SX-RFF-view-404-bt-De6.nib
│       │       ├── StoryboardResources.csx
│       │       ├── Walkthrough.storyboard
│       │       ├── Walkthrough.storyboardc/
│       │       │   ├── 4cK-Eu-ujv-view-YYD-CQ-DLY.nib
│       │       │   ├── CCf-Sq-ZKC-view-E33-5d-PF3.nib
│       │       │   ├── Info.plist
│       │       │   ├── Kgw-Zr-aQ8-view-3jo-us-oYx.nib
│       │       │   ├── MainMenu.nib
│       │       │   ├── NSViewController-CCf-Sq-ZKC.nib
│       │       │   ├── NSViewController-Kgw-Zr-aQ8.nib
│       │       │   ├── NSViewController-hlZ-SX-RFF.nib
│       │       │   ├── NSWindowController-B8D-0N-5wS.nib
│       │       │   ├── NSWindowController-plf-cC-dqu.nib
│       │       │   ├── XdO-WJ-HvK-view-Tof-WT-yQ6.nib
│       │       │   ├── XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
│       │       │   └── hlZ-SX-RFF-view-404-bt-De6.nib
│       │       └── index.workbook
│       ├── tableview/
│       │   ├── NSTableView.workbook
│       │   └── README.md
│       ├── toolbars/
│       │   ├── README.md
│       │   └── toolbars.workbook/
│       │       ├── index.workbook
│       │       └── toolbar-resources.csx
│       ├── ui-in-code/
│       │   ├── README.md
│       │   └── codebasedui.workbook/
│       │       └── index.workbook
│       └── webbrowser/
│           ├── README.md
│           └── webbrowser.workbook/
│               ├── Main.storyboard
│               ├── Main.storyboardc/
│               │   ├── Info.plist
│               │   ├── MainMenu.nib
│               │   ├── MainViewController.nib
│               │   ├── MainWindowController.nib
│               │   └── XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
│               ├── StoryboardResources.csx
│               └── index.workbook
├── machine-learning/
│   └── ML - Getting Started - Sentiment Analysis.workbook/
│       ├── index.workbook
│       ├── ml-sent.csx
│       ├── sentiment-imdb-train.txt
│       └── sentiment-yelp-test.txt
├── workbooks/
│   ├── README.md
│   ├── getting-started/
│   │   ├── meta.json
│   │   └── welcome.workbook
│   ├── meta.json
│   └── visualizers/
│       ├── README.md
│       ├── Visualizers-console.workbook
│       ├── Visualizers-ios.workbook
│       ├── Visualizers-mac.workbook
│       ├── Visualizers-wpf.workbook
│       └── meta.json
├── wpf/
│   ├── README.md
│   ├── getting-started/
│   │   ├── HelloWPF.workbook
│   │   ├── hello-wpf-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── user-interface/
│       ├── graphics/
│       │   └── PenroseTriangle.workbook/
│       │       └── index.workbook
│       └── meta.json
└── xamarin-forms/
    ├── README.md
    ├── advanced/
    │   ├── MandelbrotTouch.workbook/
    │   │   ├── BitmapInfo.csx
    │   │   ├── BmpMaker.csx
    │   │   ├── Complex.csx
    │   │   ├── FormsInit.csx
    │   │   ├── Mandelbrot.png.txt
    │   │   ├── MandelbrotModel.csx
    │   │   └── index.workbook
    │   ├── RPNCalculator/
    │   │   ├── README.md
    │   │   ├── RpnCalculator-ios.workbook
    │   │   └── RpnCalculator.workbook
    │   └── meta.json
    ├── application-fundamentals/
    │   ├── database/
    │   │   └── database.workbook/
    │   │       ├── FormsInit.csx
    │   │       └── index.workbook
    │   ├── files/
    │   │   └── files.workbook/
    │   │       ├── FormsInit.csx
    │   │       └── index.workbook
    │   ├── hierarchical-navigation/
    │   │   └── hierarchical-navigation.workbook/
    │   │       ├── FormsInit.csx
    │   │       └── index.workbook
    │   ├── meta.json
    │   └── text-to-speech/
    │       └── text-to-speech.workbook/
    │           ├── FormsInit.csx
    │           └── index.workbook
    ├── getting-started/
    │   ├── GettingStartedWithXamarinForms-ios.workbook
    │   ├── GettingStartedWithXamarinForms.workbook
    │   └── meta.json
    ├── meta.json
    └── user-interface/
        ├── alerts/
        │   └── alerts.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── button/
        │   └── button.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── editor/
        │   └── editor.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── entry/
        │   └── entry.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── image/
        │   └── image.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── label/
        │   └── label.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── layout-options/
        │   └── layout-options.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── listview/
        │   ├── ListView.workbook
        │   ├── ListView1-android.workbook
        │   └── ListView1-ios.workbook
        ├── map/
        │   └── map.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── margins-padding/
        │   └── margins-and-padding/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── meta.json
        ├── picker/
        │   └── picker.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── slider/
        │   └── slider.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── stacklayout/
        │   └── stacklayout.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── switch/
        │   └── switch.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── tabbedpage/
        │   └── tabbedpage.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── webview/
        │   └── webview.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        └── xaml/
            └── LoadXaml.workbook

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.DS_Store
[Bb]in/
graphics/tiny-renderer/Renderer/obj/


================================================
FILE: LICENSE.md
================================================
The code in this repository is licensed under the terms of the MIT license:

The MIT License (MIT)
Copyright (c) 2016 Microsoft, Inc

Permission is hereby granted, free of charge, 
to any person obtaining a copy of this software and 
associated documentation files (the "Software"), to 
deal in the Software without restriction, including 
without limitation the rights to use, copy, modify, 
merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom 
the Software is furnished to do so, 
subject to the following conditions:

The above copyright notice and this permission notice 
shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# Sample Workbooks

This repository contains workbooks to learn various APIs across
Android, iOS and Windows.

**If you are looking to file issues or contribute to development of
the Xamarin Workbooks app, please head to
https://github.com/Microsoft/workbooks.**

---

To use these samples, simply checkout this repository and open any of the `.workbook` files 
with [Xamarin Workbooks](https://developer.xamarin.com/guides/cross-platform/workbooks/)

The examples are organized by categories:

* SDK - This directory contains sample integrations and accompanying support materials for integrating with Xamarin Workbooks.
* Azure - Samples showing how to use Azure services, like Cognitive Services and MobileServices
* CSharp - Walkthrough various new features in the C# language
* Graphics - The TinyRender graphics tutorial, 2D graphics with SkiaSharp and 3D graphics with Urho
* Xamarin-Forms - cross-platform mobile apps with Xamarin.Forms

Platform specific:
* Android - Android workbooks
* Mac - Mac workbooks 
* iOS - iOS workbooks 
* WPF - Windows Presentation Foundation workbooks


================================================
FILE: SDK/.gitignore
================================================
bin/
obj/
*.user*


================================================
FILE: SDK/README.md
================================================
# Custom Integrations with Xamarin Workbooks

This directory contains sample integrations and accompanying support materials
for integrating with Xamarin Workbooks.

See the [full SDK documentation][docs] for details on the Xamarin Developer site.

[docs]: https://developer.xamarin.com/guides/cross-platform/workbooks/sdk/


================================================
FILE: SDK/Samples/KitchenSink/AgentIntegration.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;

using Xamarin.Interactive;
using Xamarin.Interactive.Representations;

[assembly: AgentIntegration (typeof (KitchenSinkIntegration.AgentIntegration))]

namespace KitchenSinkIntegration
{
	class AgentIntegration : IAgentIntegration
	{
		const string TAG = nameof (AgentIntegration);

		public void IntegrateWith (IAgent agent)
		{
			agent.RepresentationManager.AddProvider (new SampleRepresentationProvider ());
		}

		class SampleRepresentationProvider : RepresentationProvider
		{
			public override bool HasSensibleEnumerator (IEnumerable enumerable)
			{
				// for some reason rendering Arrays as enumerables just doesn't
				// make sense in the context of this agent integration!
				if (enumerable is Array)
					return false;

				return base.HasSensibleEnumerator (enumerable);
			}

			public override IEnumerable<object> ProvideRepresentations (object obj)
			{
				// we really like green, so return it for all objects!
				yield return new Color (0, 1, 0, 0.5);
			}
		}
	}
}

================================================
FILE: SDK/Samples/KitchenSink/Api.cs
================================================
using System;

using Xamarin.Interactive.Representations;

public static class KitchenSink
{
	static readonly Random random = new Random ();

	public static Color RandomColor ()
		=> new Color (random.NextDouble (), random.NextDouble (), random.NextDouble ());
}

================================================
FILE: SDK/Samples/KitchenSink/KitchenSink.workbook
================================================
---
uti: com.xamarin.workbook
platform: MacMobile
---

```csharp
#r "bin/KitchenSinkIntegration.dll"
```

```csharp
KitchenSink.RandomColor ()
```

```csharp
new KitchenSinkIntegration.Person ("Aaron")
```

```csharp
new [] { 1, 2, 3 }
```

================================================
FILE: SDK/Samples/KitchenSink/KitchenSinkIntegration.csproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{AA977F86-97C7-47E0-9A53-300799386F30}</ProjectGuid>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <RootNamespace>KitchenSinkIntegration</RootNamespace>
    <AssemblyName>KitchenSinkIntegration</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <TargetFrameworkProfile>Profile78</TargetFrameworkProfile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin</OutputPath>
    <DefineConstants>DEBUG;</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="AgentIntegration.cs" />
    <Compile Include="Api.cs" />
    <Compile Include="Person.cs" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="KitchenSinkIntegration.js">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <ItemGroup>
    <Reference Include="Xamarin.Interactive" />
  </ItemGroup>
  <ItemGroup>
    <None Include="KitchenSink.workbook" />
  </ItemGroup>
  <Import Project="..\XamarinInteractive.targets" />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
</Project>


================================================
FILE: SDK/Samples/KitchenSink/KitchenSinkIntegration.js
================================================
console.log("hello from some third party code => %O", xamarin.interactive)

var PersonRenderer = (function () {
  function PersonRenderer () {
  }

  PersonRenderer.prototype.cssClass = "renderer-third-party-person";

  PersonRenderer.prototype.getRepresentations = function () {
    return [
      { shortDisplayName: "Person" }
    ]
  };

  PersonRenderer.prototype.bind = function (renderState) {
    console.log("PersonRenderer: bind: %O", renderState)
    this.renderState = renderState;
  };

  PersonRenderer.prototype.render = function (target) {
    console.log("PersonRenderer: render %O to %O", this.renderState, target)
    var elem = document.createElement("div");
    elem.innerHTML = "<strong>Person: <em>" + this.renderState.source.Name + "</em></strong>";
    target.inlineTarget.appendChild(elem);
  }

  return PersonRenderer;
})();

xamarin.interactive.RendererRegistry.registerRenderer(
  function (source) {
    if (source.$type === "KitchenSinkIntegration.Person")
      return new PersonRenderer;
  }
);

================================================
FILE: SDK/Samples/KitchenSink/KitchenSinkIntegration.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitchenSinkIntegration", "KitchenSinkIntegration.csproj", "{AA977F86-97C7-47E0-9A53-300799386F30}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{AA977F86-97C7-47E0-9A53-300799386F30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{AA977F86-97C7-47E0-9A53-300799386F30}.Debug|Any CPU.Build.0 = Debug|Any CPU
	EndGlobalSection
EndGlobal


================================================
FILE: SDK/Samples/KitchenSink/Person.cs
================================================
using System;

using Xamarin.Interactive.Serialization;

namespace KitchenSinkIntegration
{
	public sealed class Person : ISerializableObject
	{
		public string Name { get; }

		public Person (string name)
		{
			if (name == null)
				throw new ArgumentNullException (nameof (name));

			Name = name;
		}

		void ISerializableObject.Serialize (ObjectSerializer serializer)
			=> serializer.Property (nameof (Name), Name);
	}
}

================================================
FILE: SDK/Samples/XamarinInteractive.targets
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <InteractiveSDKLocation Condition=" '$(OS)' == 'Unix' ">\Library\Frameworks\Xamarin.Interactive.framework\Versions\Current\SDK</InteractiveSDKLocation>
    <InteractiveSDKLocation Condition=" '$(OS)' != 'Unix' ">C:\Program Files (x86)\Xamarin\Workbooks\SDK</InteractiveSDKLocation>
  </PropertyGroup>
  <PropertyGroup>
    <ReferencePath>$(InteractiveSDKLocation)</ReferencePath>
  </PropertyGroup>
</Project>


================================================
FILE: SDK/typings/xamarin-interactive.d.ts
================================================
declare module "xamarin/interactive/dotnet" {
  /**
   * A .NET CultureInfo.
   * See https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx .
   */
  export interface CultureInfo {
    name: string
    lcid: number
  }

  /**
   * A serialized .NET object.
   */
  export interface ManagedObject {
    /**
     * The value of `GetType ().ToString ()` for the underlying .NET object.
     * Includes namepspace but no assembly qualification.
     */
    $type: string
  }
}

declare module "xamarin/interactive/rendering" {
  import { ManagedObject, CultureInfo } from "xamarin/interactive/dotnet"

  export enum RendererRepresentationOptions {
    None = 0,

    /**
     * The representation will always be provided the expanded render
     * targets and will not be collapsible at all.
     */
    ForceExpand = 1,

    /**
     * The representation is collapsible, but will be expanded by default.
     */
    ExpandedByDefault = 2,

    /**
     * The representation is collapsible and will be collapsed by default if
     * it is the only or initially selected renderer, and otherwise expanded
     * automatically when selected from the menu.
     */
    ExpandedFromMenu = 4,

    /**
     * The display name of the representation will be suppressed in the
     * representation button label and shown only in the button's menu,
     * but only if all other representations also have the hint.
     */
    SuppressDisplayNameHint = 8
  }

  /**
   * One (of perhaps many) representation(s) for a given renderer.
   */
  export interface RendererRepresentation {
    /**
     * The name to show in the representation drop-down menu in the client.
     */
    shortDisplayName: string
    /**
     * An optional piece of state for use by the renderer.
     */
    state?: any
    /**
     * Optional. Defaults to RendererRepresentationOptions.None.
     */
    options?: RendererRepresentationOptions
    /**
     * Optional numerical value to determine sort order of renderers in the
     * client's drop-down menu. Defaults to 0.
     */
    order?: number
  }

  /**
   * Provides access to the HTML targets during Renderer.render.
   */
  export interface RenderTarget {
    /**
     * The selected representation to render.
     */
    representation: RendererRepresentation
    /**
     * The container element to modify for the 'collapsed' rendering.
     */
    inlineTarget: HTMLElement
    /**
     * The container element to modify for the 'expanded' rendering.
     */
    expandedTarget: HTMLElement
    /**
     * Returns true if the representation is currently expanded.
     */
    isExpanded: boolean
  }

  /**
   * Provides access to the serialized object being rendered, and other state.
   */
  export interface RenderState {
    /**
     * The state of the parent object, if there is one. Renderers might choose
     * to layout differently depending on whether or not they are being displayed
     * as part of a member row in an interactive object table, for example.
     */
    parentState: RenderState
    /**
     * The serialized .NET source object.
     */
    source: ManagedObject
    /**
     * Optional CultureInfo.
     */
    cultureInfo?: CultureInfo
  }

  /**
   * Provides custom rendering(s) for ManagedObjects.
   */
  export interface Renderer {
    /**
     * The CSS class added to both the inline rendering target and the expanded
     * rendering target.
     */
    cssClass: string
    /**
     * The representation(s) provided by this Renderer.
     */
    getRepresentations(): RendererRepresentation[]
    /**
     * Called once when an object is ready for rendering (though some other
     * renderer may currently be selected). Useful for doing one-time work.
     */
    bind(renderState: RenderState): void
    /**
     * Called when it is time to render the serialized object into the HTML target(s).
     */
    render(target: RenderTarget): void

    /**
     * Optional; set to false to prevent this renderer's representations from
     * showing up in the client's drop-down menu.
     */
    isEnabled?: boolean
    /**
     * Optional; set to true to enable showing the expanded rendering target.
     */
    canExpand?: boolean
    /**
     * Optional. Notifies renderer when a collapse occurs, in case extra work is
     * needed beyond the work done during render.
     */
    collapse?(): void
    /**
     * Optional. Notifies renderer when an expand occurs, in case extra work is
     * needed beyond the work done during render.
     */
    expand?(): void
  }

  /**
   * Accessible via xamarin.interactive.RendererRegistry, this is used to
   * register renderers.
   */
  export class RendererRegistry {
    /**
     * Register a renderer factory method. Typically this method will check the
     * type of the source object, and return an appropriate Renderer if it is
     * a type the caller wants to handle.
     */
    registerRenderer(factory: (source: ManagedObject) => Renderer): void
  }
}


================================================
FILE: android/README.md
================================================
Android Workbooks
============

* Getting Started
* User Interface


================================================
FILE: android/getting-started/AndroidAppBasics.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# Android App Basics

In this interactive tutorial, you will learn the basics of 
creating an Android application using Xamarin.Android.


## Android User Interface

The graphical user interface for an Android app is constructed from 
*widgets* such as text fields, buttons, and checkboxes. Widgets can be 
thought of as the building blocks that you use to create a user 
interface. `View` widgets are used to show text, display graphics, and 
interact with the user. `ViewGroup` widgets are invisible containers 
that arrange other widgets on the screen. This tutorial demonstrates 
how to build a basic user interface for an Android app by creating 
these widgets, laying them out on the screen, and wiring them up for 
user interaction. 


## Getting Started

Start by importing several namespaces that will be required for the code
in the rest of this tutorial:

```csharp
using Android.App;
using Android.Widget;
using Android.OS;
```

In Android, each screen is controlled by an `Activity`. The `Activity` 
is responsible for managing user interaction within a screen of information.
There is only one `Activity` in a Xamarin Workbook. The following code
creates a reference to this `Activity` object: 

```csharp
var rootActivity = StartedActivities.First ();
```

This `rootActivity` reference is used throughout the remainder of 
this tutorial. 


## Defining the User Interface

The first step in creating a UI is to define a `ViewGroup` that will 
hold the various widgets that comprise the UI of the `Activity`. Next, 
one or more `View`s are added to this `ViewGroup` and their parameters are 
configured to set how and where each `View` is displayed within the 
`ViewGroup`. 


### Creating a Layout

`LinearLayout` is a `ViewGroup` that arranges its child `View`s from 
top to bottom (or from left to right) as they are added. Instantiate a 
`LinearLayout` object and set its orientation to vertical: 

```csharp
var layout = new LinearLayout (rootActivity);
layout.Orientation = Orientation.Vertical;

```

Setting the orientation to vertical causes widgets to be arranged 
from top to bottom of the screen as they are added to the layout. 

### Adding a Button

The first widget to add to this layout is a `Button`. Instantiate a 
`Button` object, set its display text to **Click Me!**, and add the
button to the layout: 

```csharp
Button button = new Button(rootActivity);
button.Text = "Click Me!";
layout.AddView (button);
```

Run the following code to display the resulting user interface on the 
screen: 

```csharp
rootActivity.SetContentView(layout);
```

When you click the button, the app does not respond. That is because 
there is no code to handle the button's click event. This code will be 
added later in this tutorial. 


### Adding a TextView

The next widget to add to this layout is a `TextView`. Instantiate a 
`TextView` object, initialize its text, and add it to the layout: 

```csharp
TextView textView = new TextView(rootActivity);
textView.Text = "This Space is for Rent";
layout.AddView (textView);
```

When you run this code, a `TextView` is created and its message is 
displayed below the button. Run the following code, change 
the text to something different, and then run it again: 

```csharp
textView.Text = "This Space is Taken";
```

### Modifying View Layout Parameters

You can call methods on a `View` object to modify how it looks after it 
is instantiated. Run the following line of code to center the 
`TextView` within the `LinearLayout`: 

```csharp
textView.Gravity = Android.Views.GravityFlags.CenterHorizontal;
```

The `TextView` would look better if it had more space around it. Run the 
following code to add padding (20 pixels top and bottom, 10 pixels on 
each side): 


```csharp
textView.SetPadding(10, 20, 10, 20);
```

To make the text easier to read, run the following line of code to 
change the color of the text to yellow: 

```csharp
textView.SetTextColor(Android.Graphics.Color.Yellow);
```

At this point, the app has a simple (though passive) user interface 
that is displayed in a single `Activity`. The next step is to add code 
to handle user input. 


## Responding to User Input

After the app's user interface is designed, the next step is to create 
event handlers to respond to user input. The following examples 
demonstrate how to create event handlers to respond to user clicks on 
the button. 

### Creating an Event Handler

There are a number of different ways that you can write code to handle 
user-triggered events. The following code implements an *anonymous 
delegate* to handle the button click event. This one-line event 
handler changes the text on the button face when it is clicked: 

```csharp
button.Click += delegate { button.Text = "This Button was clicked"; };
```

Click the button after running this code to see the text on the button 
change. 


### Displaying a Toast

Another way to repond to user input is to display a *Toast* message 
that indicates that the button was clicked. Run this code and click the 
button again: 


```csharp
button.Click += delegate { Toast.MakeText(rootActivity, "Clicked!", ToastLength.Long).Show(); };
```

A toast message is briefly displayed near the bottom of the screen to 
indicate that the button was clicked. 

Note that the button text is *also* updated with each click. This is 
because each call to `button.Click +=` adds an additional event handler 
that responds to button clicks (i.e., it doesn't replace the previously 
defined event handler). Each event handler that is added to the button 
`Click` event is called when when the button is clicked. 


## Exercises

You have now seen the basics of how to create a Xamarin.Android user 
interface and handle user input. Here are some things you can try to 
test your understanding: 

-   Add a `count` variable and increment this count each time the 
    button is clicked. 

-   Display the new click count on the button face each time the button 
    is clicked. 

-   Try displaying the click count in the `TextView` as well as on 
    the face of the button. 


## Further Reading

In a typical Android application, you develop a user interface by 
defining its layout in an XML file. This XML file describes the 
hierarchical relationships of `View`s and `ViewGroup`s in your UI 
(rather than programmatically, as was demonstrated in this tutorial), 
and it defines the configuration parameters for each `View` and 
`ViewGroup` . For a more detailed explanation about building your first 
Android app using Xamarin Studio or Visual Studio, see 
[Hello, Android](https://developer.xamarin.com/guides/android/getting_started/hello,android/). 


================================================
FILE: android/getting-started/hello-android-workbook.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
---

# Android

```csharp
var mainActivity = StartedActivities.First();
var label = new Android.Widget.TextView(mainActivity) {
  Text = "Hello, Workbooks",
  TextSize = 36
};
mainActivity.SetContentView(label);
```


================================================
FILE: android/getting-started/meta.json
================================================
{
  "order":{
    "AndroidAppBasics.workbook":"App Basics",
    "hello-android-workbook.workbook":"Hello, Android"
  }
}


================================================
FILE: android/meta.json
================================================
{
  "order":{
    "getting-started":"Getting Started",
    "user-interface":"User Interface"
  }
}


================================================
FILE: android/user-interface/2D-drawing.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# 2D Graphics in Xamarin.Android

In this workbook, you will learn the basics of creating a custom View and 2D drawing using Xamarin.Android.

One technique for drawing 2D graphics in Android is to use the Canvas APIs. This is a powerful API that allows for very fine grained control for how 2D graphics are created. The Canvas API uses a\* painter’s model\* for 2D drawing. Settings such as colour, stroke type, are programatically applied. Methods on the Canvas object are called to perform drawing actions, which are applied in successive order on the underlying bitmap. There are two ways to obtain and draw on a `Canvas` object.

One is to create a bitmap and provide as a parameter to the `Canvas` constructor. The other way is to subclass `Android.Views.View`, and override the `OnDraw` method. Android will invoke this method each time the View needs to be draw, and will pass in a `Canvas` object to be draw on.

For this example, let’s consider the case of drawing a progress bar. Part of the bar will be red, and the other part is green.

To beging, let’s declare all the namespaces that are required for this work through and obtain a reference to the Activity that we will be drawing on:

```csharp
using System;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Graphics.Drawables.Shapes;
using Android.OS;
using Android.Views;

Activity activity=StartedActivities.First();
```

## Creating a Custom View for Drawing

The code for drawing the progress bar will be contained in a custom class that extends `Android.Views.View`. This code for this is shown in the following class:

```csharp
public class MyRedGreenBar : Android.Views.View
{
    Paint greenPaint;
    Paint redPaint;

    public MyRedGreenBar(Context context) : base(context)
    {
        greenPaint = new Paint { 
            AntiAlias=true, 
            Color = Color.Rgb(0x99,0xCC, 0)
        };
        greenPaint.SetStyle(Paint.Style.FillAndStroke);

        redPaint = new Paint {
            AntiAlias = true,
            Color = Color.Rgb(0xFF, 0x44, 0x44)
        };
        redPaint.SetStyle(Paint.Style.FillAndStroke);
    }

    protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);

        // First, fill the canvas with the red paint.
        canvas.DrawPaint(redPaint);

        // Next, draw a green rectangle that covers the left 25% of the canvaa.
        float middle = canvas.Width * 0.25f;
        canvas.DrawRect(0,0, middle, Height, greenPaint);
    }
}
```

## Display the View

To display this view, just set it as the content view for the Activity:

```csharp
activity.SetContentView(new MyRedGreenBar(activity));
```

## Further Reading

To learn more, you might want to read the [Graphics & Animation Guide](https://developer.xamarin.com/guides/android/application_fundamentals/graphics_and_animation/) in the Xamarin Developer Portal.

================================================
FILE: android/user-interface/AutoCompleteTextView.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# AutoCompleteTextView

This guide will demonstrate how to use an AutoCompleteTextView in an Android application. An AutoCompleteTextView will display a list of suggestions that match the text a user has entered into a TextView. An AutoCompleteTextView doesn’t work alone - it requires the assistance of another widget which must extend `Android.Widget.BaseAdapter`. The adapter is a special class that will display a individual item from a list in the drop down list UI that is presented by the AutoCompleteTextView.

First, let’s import the necessary namespaces that we need, and declare a list hat holds the names of some monkeys.

```csharp
using System;
using Android.App;
using Android.Util;
using Android.Views;
using Android.Widget;

// Get a reference to the Activity.
Activity activity = StartedActivities.First();

// A small list of some different types of monkeys
List<String> allTheMonkeys = new List<String> { "Allen's swamp monkey",
  "Black capuchin", "Black-headed marmoset", "Black-headed night monkey", "Black-shanked douc", 
  "Cotton top tamarin",
  "Drill",
  "Gee's golden lemur", "Geoffrey's tamarin", "Gelada", "Golden lion Tamarin", "Grivet", 
  "Japanese macaque", 
  "Lesula", 
  "Mandril", 
  "Yellow baboon"
};
```

We will need to create an `ArrayAdapter<String>` and assign it to the AutoTextCompleteTextView widget. In this example, each row in the AutoCompleteTextView will use a built-in Android layout, the `Android.Resource.Layout.SimpleListItem1`:

```csharp
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, Android.Resource.Layout.SimpleListItem1, allTheMonkeys);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);

AutoCompleteTextView actv = new AutoCompleteTextView(activity);
actv.Adapter = adapter;
```

In the next snippet, we add the `actv` to the Activity, want to add some padding to the views. Typically, one uses *device-independent pixels (DPs)* for positioning views on an Android layout. However, the `SetPadding` method takes pixels. The `DP2Pixel` method will take a DP value and convert that to pixels appropriate to the device.

```csharp
int DP2Pixel(int dpValue)
{
    float density = activity.Resources.DisplayMetrics.Density;
    int paddingDP = (int) (dpValue * density);
    return paddingDP; 
}

int paddingLeft = DP2Pixel(10);
int paddingRight = paddingLeft;
int paddingTop = DP2Pixel(20);
int paddingBottom = DP2Pixel(9);

actv.SetPadding(paddingLeft, 0, paddingRight, 0);

LinearLayout rootLayout = new LinearLayout(activity);
TextView label = new TextView(activity);
label.Text = "Pick a Monkey:";
label.SetPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);

rootLayout.Orientation = Orientation.Vertical;
rootLayout.AddView(label);
rootLayout.AddView(actv);

activity.SetContentView(rootLayout);
```

## Further Reading

You may want to check out the ListView and the Spinner workbooks as they are very similar to the AutoCompleteTextView control. To display more complex data, such as a POCO, it is better to create a custom Adapter in C#; you can learn more about this by consulting the [Xamarin ListView & Adapters guide](https://developer.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/).

================================================
FILE: android/user-interface/PropertyAnimation.workbook
================================================
```json
{"platform":"Android","uti":"com.xamarin.workbook","packages":[]}
```

# Android View Property Animation

In this interactive tutorial, you will learn the basics of `View`
property animation in Xamarin.Android.

For a more detailed account of the various Android animation APIs,
please checkout out [the
documentation](https://developer.xamarin.com/guides/android/application_fundamentals/graphics_and_animation/
"Xamarin.Android animation documentation").

## Getting Started

We’ll start by importing several namespaces that we will need.

```csharp
using Android.Views;
using Android.Widget;
using Android.Util;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Graphics.Drawables.Shapes;
```

There is only one `Activity` in a Xamarin Workbook. Grab the first so
that we can adjust its content later (for information on
`StartedActivities`, type `help` in a workbook code entry).

```csharp
var rootActivity = StartedActivities.First ();
```

`DimToPixels` is a handy utility function we’ll use later on.

```csharp
int DimToPixels (int dip, ComplexUnitType type = ComplexUnitType.Dip) =>
	(int)TypedValue.ApplyDimension (type, dip, rootActivity.Resources.DisplayMetrics);
```

## World Clocks

Our first example demonstrates animating a collection of `TextClock`
views. We start with a set of timezones.

Feel free to adjust this list however you like.

```csharp
var timezones = new[] {
	"UTC", // The World!
	"US/Pacific", // San Francisco
	"US/Eastern", // Boston
	"America/Buenos_Aires",
	"Europe/Copenhagen",
	"Europe/London"
};
```

Pick a color to use for the clockface.

```csharp
var clockColor = Color.Rgb (0x73, 0x81, 0x82)
```

Creating and styling a `TextClock` is fairly straightforward. We make
the background a circle using `OvalShape`.

```csharp
TextClock CreateClockForZone (string zone)
{
	var clock = new TextClock (rootActivity) {
		TimeZone = zone,
		Gravity = GravityFlags.Center,
	};

	var background = new ShapeDrawable (new OvalShape ());
	background.Paint.Color = clockColor;
	clock.Background = background;

	var padding = DimToPixels (12);
	clock.SetPadding (padding, padding, padding, padding);

	var size = DimToPixels (90);
	clock.SetMinimumWidth  (size);
	clock.SetMinimumHeight (size);

	clock.SetTextSize (ComplexUnitType.Sp, 15);
	clock.SetTextColor (Color.White);

	return clock;
}
```

### Animation

Android provides a `ViewPropertyAnimator` that drives the
`View.Animate` method.

Properties that can be animated using this method include:

* `alpha`

* `rotation(X|Y)`

* `scale(X|Y)`

* `translation(X|Y|Z)`

* `x|y|z`

Let's make an extension method that animates the `TextClock` as it is
added to the grid.

```csharp
static void AnimateEntrance (this TextClock clock, int index)
{
	// Set the initial values to animate from
	clock.ScaleX = clock.ScaleY = 0.3f;
	clock.Alpha = 0;

	// Animate in the new values
	clock.Animate ()
		.Alpha (1)
		.ScaleX (1)
		.ScaleY (1)
		.SetStartDelay (index * 100 + 10)
		.SetDuration (400)
		.Start ();
}
```

So now we can:

1. Create a `TextClock` for each of our time zones.

2. Add it to the grid.

3. Set up the entrance animation.

```csharp
void AddClocksToGrid (GridLayout grid, IList<string> zones)
{
	var index = 1;
	foreach (var zone in zones) {
		var clock = CreateClockForZone (zone);
		grid.AddView (clock);

		clock.AnimateEntrance (index++);
	}
}
```

### Putting it all together

Finally, we set up our content `GridLayout` and add the clocks.

```csharp
var rootGrid = new GridLayout (rootActivity) {
	ColumnCount = 3,
	UseDefaultMargins = true,
	AlignmentMode = GridAlign.Bounds,
};
var padding = DimToPixels (16, ComplexUnitType.Dip);
rootGrid.SetPadding (padding, padding, padding, padding);
rootActivity.SetContentView (rootGrid, new ViewGroup.LayoutParams (-1, -1));
```

```csharp
AddClocksToGrid (rootGrid, timezones)
```

### Exercises

You have now seen the basics of how `View` animation works in Android.

Here are some things you can try, to test your understanding:

* Animate the rotation of the clock. Note that the rotation value is
  in **degrees**.

* Increase the **size of the clock text**. What happens to the clock’s
  shape? Can you fix it?

* Combine what you’ve learned in previous lessons about the `Touch`
  event. Can you make the clock **shrink a bit when tapped**?

* Replace the clock with a **layout** that includes the clock and a
  **timezone label**.



================================================
FILE: android/user-interface/listview.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# Using a ListView in Xamarin.Android

This guide will demonstrate how to use a ListView in an Android application. Although it is an older UI widget, it is great for quick lists. The ListView doesn’t work by itself, the data displayed in a ListView by a class that extends `Android.Widget.BaseAdapter`. In this workbook, we won’t create our own class, instead we’ll just use `Android.Widget.ArrayAdapter<String>` class.

Let’s get started by importing the namespaces and initializing a list of string to display in the ListView. We will also get a reference to the Android Activity used by this workbook:

```csharp
using System;
using Android.App;
using Android.Views;
using Android.Widget;

Activity activity = StartedActivities.First();
List<String> allTheMonkeys =  new List<String> { "Allen's swamp monkey",
  "Black capuchin", "Black-headed marmoset", "Black-headed night monkey", "Black-shanked douc", 
  "Cotton top tamarin",
  "Drill",
  "Gee's golden lemur", "Geoffrey's tamarin", "Gelada", "Golden lion Tamarin", "Grivet", 
  "Japanese macaque", 
  "Lesula", 
  "Mandril", 
  "Yellow baboon"
};
```

We will need to create an `ArrayAdapter<String>` and assign it to the ListView widget. In this example, each row in the ListView will use a built-in Android layout, the `Android.Resource.Layout.SimpleListItem1`:

```csharp
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, Android.Resource.Layout.SimpleListItem1, allTheMonkeys);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);

ListView listview = new ListView(activity);
listview.Adapter = adapter;

// Set an event handler for when the user makes a selection from the spinner.
listview.ItemClick += (object sender, AdapterView.ItemClickEventArgs e) => {
    ListView l = (ListView) sender;
    string message = String.Format("Your favourite monkey is {0}.", allTheMonkeys[e.Position]);
    Toast.MakeText(activity, message, ToastLength.Short).Show();
} ;
```

In the next snippet, we add the `listview` to the Activity, want to add some padding to the views. Typically, one uses *device-independent pixels (DPs)* for positioning views on an Android layout. However, the `SetPadding` method takes pixels. The `DP2Pixel` method will take a DP value and convert that to pixels appropriate to the device.

```csharp
int DP2Pixel(int dpValue)
{
    float density = activity.Resources.DisplayMetrics.Density;
    int paddingDP = (int) (dpValue * density);
    return paddingDP; 
}

int paddingLeft = DP2Pixel(10);
int paddingRight = paddingLeft;
int paddingTop = DP2Pixel(20);
int paddingBottom = DP2Pixel(9);

listview.SetPadding(paddingLeft, 0, paddingRight, 0);

LinearLayout rootLayout = new LinearLayout(activity);
TextView label = new TextView(activity);
label.Text = "Pick a Monkey:";
label.SetPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);

rootLayout.Orientation = Orientation.Vertical;
rootLayout.AddView(label);
rootLayout.AddView(listview);

activity.SetContentView(rootLayout);
```

## Further Reading

You may want to check out the Spinner and the AutoCompleteTextView workbooks as they are very similar to the ListView control. To display more complex data, such as a POCO, it is better to create a custom Adapter in C#; you can learn more about this by consulting the [Xamarin ListView & Adapters guide](https://developer.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/).

================================================
FILE: android/user-interface/meta.json
================================================
{
  "order":{
    "2D-drawing.workbook":"2D Drawing",
    "AutoCompleteTextView.workbook":"AutoComplete Text View",
    "listview.workbook":"ListView",
    "popupmenus.workbook":"Popup Menus",
    "PropertyAnimation.workbook":"Property Animation",
    "spinner.workbook":"Spinner",
    "switch.workbook":"Switch",
    "views.workbook":"Views"
  }
}


================================================
FILE: android/user-interface/popupmenus.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# Android Popup Menus

A *Popup menu* is a menu that is displayed in a window that is anchored 
to a `View`. In this interactive tutorial, you will learn how to create 
a single popup menu item and attach it to a `TextView`. 

## Getting Started

Start by importing several namespaces that will be required for the code
in the rest of this tutorial:

```csharp
using Android.App;
using Android.Widget;
using Android.OS;
```

Next, create an Android `Activity` and instantiate a screen layout:

```csharp
var rootActivity = StartedActivities.First ();
var layout = new LinearLayout (rootActivity);
layout.Orientation = Orientation.Vertical;
rootActivity.SetContentView(layout);
```

Because `PopupMenu` must be anchored to a `View`, the next step is add 
a `TextView` to the layout. This `TextView` will anchor the popup menu: 

```csharp
TextView textView = new TextView(rootActivity);
textView.Text = "Click to Launch Popup Menu";
layout.AddView (textView);
```

When you run this code, a `TextView` should be displayed near
the top of the screen.

## Adding a Popup Menu

`PopupMenu` is a `View` that displays a single menu item. Run the 
following code to create a new `PopupMenu` and set its title:

```csharp
PopupMenu popup = new PopupMenu(rootActivity, textView);
popup.Menu.Add(new Java.Lang.String("This is a Popup Menu"));
```

To display a `PopupMenu`, call its `Show` method. The following code
causes the popup menu instantiated above to be displayed when the
`TextView` is clicked. Run this code and click the `TextView` to see
what happens:

```csharp
textView.Click += (s, arg) => {
    popup.Show();
};
```

Clicking the `TextView` causes the **This is a Popup Menu** menu item 
to be displayed. 

In the above code, a *lambda exression* is used to implement the event
handler for the `TextView` click event. The lambda expression code (the
code within the curly braces) calls the popup menu's `Show` method when
the `TextView` is clicked.

## Handling Menu Events

When the user selects a menu item, the `MenuItemClick` event is raised. 
The following code displays a `Toast` when the menu item is clicked. 
Run the following code, click the `TextView`, and then click the menu 
to see what happens: 

```csharp
popup.MenuItemClick += (s, arg) => {
    Toast.MakeText(rootActivity, arg.Item.TitleFormatted + " selected", ToastLength.Long).Show();
};
```

The argument passed in the event contains a reference to the popup menu
item. In the above code, the title of the selected menu item is extracted
(via the passed `Item` reference) and displayed in the toast message.

When the menu item is dismissed, its `DismissEvent` is raised. Run the 
following code, click the `TextView`, and then click the screen to 
dismiss the menu item: 

```csharp
popup.DismissEvent += (s, arg) => {
    Toast.MakeText(rootActivity, "Dismissed", ToastLength.Long).Show();
};
```

When you dismiss the menu item, the `DismissEvent` handler above 
displays a toast to indicate that the `DismissEvent` handler was called.

## Exercises

You have now seen the basics of how to use `PopupMenu` in a
Xamarin.Android application. Here are some things you can try to test
your understanding:

1. Modify the `MenuItemClick` event handler to display the
   menu item's `ItemId` in the toast. (Hint: use Workbook code
   completion to see which properties and methods are available from
   the `Item` reference.)

2. Is it possible to modify the `DismissEvent` to retrieve and
   display the menu item's title from the argument passed to 
   `DismissEvent`?


================================================
FILE: android/user-interface/spinner.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# Using a Spinner in Xamarin.Android

This guide will demonstrate how to use a Spinner in an Android application. The Spinner doesn’t work by itself, the data displayed in a Spinner is displayed by a class that extends `Android.Widget.BaseAdapter`. In this workbook, we won’t create our own class, instead we’ll just use `Android.Widget.ArrayAdapter<String>` class.

Let’s get started by importing the namespaces and initializing a list of string to display in the Spinner. We will also get a reference to the Android Activity used by this workbook:

Start by importing the namespaces that will be required for the rest of this workbook and get a reference to the Activity:

```csharp
using System;
using Android.App;
using Android.Views;
using Android.Widget;

Activity activity = StartedActivities.First();
List<String> allTheMonkeys =  new List<String> { "Allen's swamp monkey",
  "Black capuchin", "Black-headed marmoset", "Black-headed night monkey", "Black-shanked douc", 
  "Cotton top tamarin",
  "Drill",
  "Gee's golden lemur", "Geoffrey's tamarin", "Gelada", "Golden lion Tamarin", "Grivet", 
  "Japanese macaque", 
  "Lesula", 
  "Mandril", 
  "Yellow baboon"
};
```

We will need to create an `ArrayAdapter<String>` and assign it to the Spinner widget. In this example, each row in the Spinner will use a built-in Android layout, the `Android.Resource.Layout.SimpleSpinnerItem`. We can also control the layout used in the Spinner’s drop down list using the `SetDropDownViewResource method`:

```csharp
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, Android.Resource.Layout.SimpleSpinnerItem, allTheMonkeys);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);

Spinner spinner = new Spinner(activity);
spinner.Adapter = adapter;

// Set an event handler for when the user makes a selection from the spinner.
spinner.ItemSelected += (sender, args) => {
    Spinner s= (Spinner) sender;
    AdapterView.ItemSelectedEventArgs e = (AdapterView.ItemSelectedEventArgs) args;
    string message = String.Format("Your favourite monkey is {0}.", allTheMonkeys[e.Position]);
    Toast.MakeText(activity, message, ToastLength.Short).Show();
};
```

In the next snippet, we add the `spinner` to the Activity. Typically, one uses *device-independent pixels (DPs)* for positioning views on an Android layout. However, the `SetPadding` method takes pixels. The `DP2Pixel` method will take a DP value and convert that to pixels appropriate to the device.

```csharp
int DP2Pixel(int dpValue)
{
    float density = activity.Resources.DisplayMetrics.Density;
    int paddingDP = (int) (dpValue * density);
    return paddingDP; 
}

int paddingLeft = DP2Pixel(10);
int paddingRight = paddingLeft;
int paddingTop = DP2Pixel(20);
int paddingBottom = DP2Pixel(9);

spinner.SetPadding(paddingLeft, 0, paddingRight, 0);

LinearLayout rootLayout = new LinearLayout(activity);
TextView label = new TextView(activity);
label.Text = "Pick a Monkey:";
label.SetPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);

rootLayout.Orientation = Orientation.Vertical;
rootLayout.AddView(label);
rootLayout.AddView(spinner);

activity.SetContentView(rootLayout);
```

## Further Reading

You may want to check out the ListViewand the AutoCompleteTextView workbooks as they are very similar to the Spinner control. To display more complex data, such as a POCO, it is better to create a custom Adapter in C#; you can learn more about this by consulting the [Xamarin ListView & Adapters guide](https://developer.xamarin.com/guides/android/user_interface/working_with_listviews_and_adapters/).

================================================
FILE: android/user-interface/switch.workbook
================================================
---
uti: com.xamarin.workbook
platform: Android
packages: []
---

# Android Switches

In this interactive tutorial, you will learn the basics of
working with the Android `Switch` widget in Xamarin.Android.
The `Switch` widget allows a user to toggle between two states
such as **ON** and **OFF**.

## Getting Started

Start by importing several namespaces that will be required for the code
in the rest of this tutorial:

```csharp
using Android.App;
using Android.Widget;
using Android.OS;
```

Next, create an Android `Activity` and instantiate a screen layout to host 
the `Switch`: 

```csharp
var rootActivity = StartedActivities.First ();
var layout = new LinearLayout (rootActivity);
layout.Orientation = Orientation.Vertical;
rootActivity.SetContentView(layout);
```

This `LinearLayout` is the `ViewGroup` that manages views on the 
screen. The only view that will be added to this layout is a `Switch`, 
but you may add more views in the exercises at the end of this 
tutorial. 

## Creating a Switch

Run the following code to create a `Switch` object and display it on 
the screen:

```csharp
Switch mySwitch = new Switch (rootActivity);
layout.AddView (mySwitch);
```

The `Switch` defaults to the **OFF** state. Repeatedly click the 
`Switch` to toggle it **ON** and **OFF**. You should see the `Switch` 
slide to the right and become highlighted when it is turned **ON**. 
Also, each click causes a sound to be produced. 

## Toggling the Switch

You can programmatically turn the switch **ON** and **OFF** by changing 
its `Checked` property. Make sure the switch is **OFF**, and then run 
the following line of code to switch it back to **ON**: 

```csharp
mySwitch.Checked = true;
```

Setting the `Checked` property to `false` turns the switch back **OFF**: 

```csharp
mySwitch.Checked = false;
```

You can use the `Checked` property to programatically change the value 
of the `Switch` to your chosen default state when the app starts up. 

## Labeling the Switch

Often is is useful to a attach a label to a `Switch` to indicate what it
does. When you set the `Switch`'s `Text` property to a string, that string is
displayed next to the `Switch`:

```csharp
mySwitch.Text = "Label for switch"
```

## Handling Switch Events

When the `Switch`'s value changes, it raises a `CheckedChange` event. The 
following code captures this event and displays a `Toast` message. Run 
this code and repeatedly click the `Switch` to see what happens: 

```csharp
mySwitch.CheckedChange += delegate(object sender, CompoundButton.CheckedChangeEventArgs e) {
    if (e.IsChecked) 
        Toast.MakeText(rootActivity, "Switch was turned ON!", ToastLength.Long).Show();
    else
        Toast.MakeText(rootActivity, "Switch was turned OFF", ToastLength.Long).Show();
}
```

When the Switch button is clicked, the `IsChecked` property of the event 
is set to indicate the state of the Switch after it was clicked. If 
`IsChecked` is `true`, the `Switch` is **ON** and a `Toast` message displays 
the new state of the `Switch`. If `IsChecked` is `false`, the `Toast` displays 
that the `Switch` has been turned **OFF**. 

## Exercises

You have now seen how to create a `Switch`, label it, modify its 
state, and handle `Switch` events. Here are some things you can try to 
test your understanding: 

-   Change the `Switch` event handler to update the `Switch` label (`Text` 
    property) rather than display a `Toast` each time the `Switch` is 
    clicked. 

-   Add a `Button` that toggles the state of the `Switch` on and off each
    time the `Button` is clicked.

-   Add a second `Switch` and implement a logical exclusive-OR operation: 
    set the `Button` text to **ON** when one and only one `Switch` is 
    turned on. Set the text to **OFF** when both `Switch`es are turned 
    off or both are turned on. 


================================================
FILE: android/user-interface/views.workbook
================================================
```json
{"platform":"Android","uti":"com.xamarin.workbook"}
```

# Android View Property Animation

In this interactive tutorial, you will learn the basics of `View` property animation in Xamarin.Android.

For a more detailed account of the various Android animation APIs, please checkout out [the documentation](https://developer.xamarin.com/guides/android/application_fundamentals/graphics_and_animation/ "Xamarin.Android animation documentation").

## Getting Started

We’ll start by importing several namespaces that we will need.

```csharp
using Android.Views;
using Android.Widget;
using Android.Util;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Graphics.Drawables.Shapes;
```

There is only one `Activity` in a Xamarin Workbook. Grab the first so that we can adjust its content later (for information on `StartedActivities`, type `help` in a workbook code entry).

```csharp
var rootActivity = StartedActivities.First ();
```

`DimToPixels` is a handy utility function we’ll use later on.

```csharp
int DimToPixels (int dip, ComplexUnitType type = ComplexUnitType.Dip) =>
	(int)TypedValue.ApplyDimension (type, dip, rootActivity.Resources.DisplayMetrics);
```

## World Clocks

Our first example demonstrates animating a collection of `TextClock` views. We start with a set of timezones.

Feel free to adjust this list however you like.

```csharp
var timezones = new[] {
	"UTC", // The World!
	"US/Pacific", // San Francisco
	"US/Eastern", // Boston
	"America/Buenos_Aires",
	"Europe/Copenhagen",
	"Europe/London"
};
```

Pick a color to use for the clockface.

```csharp
var clockColor = Color.Rgb (0x73, 0x81, 0x82)
```

Creating and styling a `TextClock` is fairly straightforward. We make the background a circle using `OvalShape`.

```csharp
TextClock CreateClockForZone (string zone)
{
	var clock = new TextClock (rootActivity) {
		TimeZone = zone,
		Gravity = GravityFlags.Center,
	};

	var background = new ShapeDrawable (new OvalShape ());
	background.Paint.Color = clockColor;
	clock.Background = background;

	var padding = DimToPixels (12);
	clock.SetPadding (padding, padding, padding, padding);

	var size = DimToPixels (90);
	clock.SetMinimumWidth  (size);
	clock.SetMinimumHeight (size);

	clock.SetTextSize (ComplexUnitType.Sp, 15);
	clock.SetTextColor (Color.White);

	return clock;
}
```

### Animation

Android provides a `ViewPropertyAnimator` that drives the `View.Animate` method.

Properties that can be animated using this method include:

* `alpha`

* `rotation(X|Y)`

* `scale(X|Y)`

* `translation(X|Y|Z)`

* `x|y|z`

Let's make an extension method that animates the `TextClock` as it is added to the grid.

```csharp
static void AnimateEntrance (this TextClock clock, int index)
{
	// Set the initial values to animate from
	clock.ScaleX = clock.ScaleY = 0.3f;
	clock.Alpha = 0;

	// Animate in the new values
	clock.Animate ()
		.Alpha (1)
		.ScaleX (1)
		.ScaleY (1)
		.SetStartDelay (index * 100 + 10)
		.SetDuration (400)
		.Start ();
}
```

So now we can:

1. Create a `TextClock` for each of our time zones.

2. Add it to the grid.

3. Set up the entrance animation.

```csharp
void AddClocksToGrid (GridLayout grid, IList<string> zones)
{
	var index = 1;
	foreach (var zone in zones) {
		var clock = CreateClockForZone (zone);
		grid.AddView (clock);

		clock.AnimateEntrance (index++);
	}
}
```

### Putting it all together

Finally, we set up our content `GridLayout` and add the clocks.

```csharp
var rootGrid = new GridLayout (rootActivity) {
	ColumnCount = 3,
	UseDefaultMargins = true,
	AlignmentMode = GridAlign.Bounds,
};
var padding = DimToPixels (16, ComplexUnitType.Dip);
rootGrid.SetPadding (padding, padding, padding, padding);
rootActivity.SetContentView (rootGrid, new ViewGroup.LayoutParams (-1, -1));
```

```csharp
AddClocksToGrid (rootGrid, timezones)
```

### Exercises

You have now seen the basics of how `View` animation works in Android.

Here are some things you can try, to test your understanding:

* Animate the rotation of the clock. Note that the rotation value is in **degrees**.

* Increase the **size of the clock text**. What happens to the clock’s shape? Can you fix it?

* Combine what you’ve learned in previous lessons about the `Touch` event. Can you make the clock **shrink a bit when tapped**?

* Replace the clock with a **layout** that includes the clock and a **timezone label**.



================================================
FILE: azure/cogs/emotion.workbook/employees.csx
================================================
// https://github.com/xamarinhq/app-acquaint/blob/2ca9e83c8344d35288e4ea7868ea6e5795a25e9c/App/Common/Acquaint.Data/SeedData.cs
using System.Collections.Generic;
public static class SeedData
{
	public static List<Acquaintance> Get()
	{
		return new List<Acquaintance>()
		{
			new Acquaintance() { FirstName = "Joseph", LastName = "Grimes", Company = "GG Mechanical", JobTitle = "Vice President", Email = "jgrimes@ggmechanical.com", Phone = "414-367-4348", Street = "2030 Judah St", City = "San Francisco", PostalCode = "94144", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/josephgrimes.jpg" },
			new Acquaintance() { FirstName = "Monica", LastName = "Green", Company = "Calcom Logistics", JobTitle = "Director", Email = "mgreen@calcomlogistics.com", Phone = "925-353-8029", Street = "230 3rd Ave", City = "San Francisco", PostalCode = "94118", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/monicagreen.jpg" },
			new Acquaintance() { FirstName = "Joan", LastName = "Mancum", Company = "Bay Unified School District", JobTitle = "Principal", Email = "joan.mancum@busd.org", Phone = "914-870-7670", Street = "448 Grand Ave", City = "South San Francisco", PostalCode = "94080", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/joanmancum.jpg" },
			new Acquaintance() { FirstName = "Alvin", LastName = "Gray", Company = "Pacific Cabinetry", JobTitle = "Office Manager", Email = "agray@pacificcabinets.com", Phone = "720-344-7823", Street = "1773 Lincoln St", City = "Santa Clara", PostalCode = "95050", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/alvingray.jpg" },
			new Acquaintance() { FirstName = "Michelle", LastName = "Wilson", Company = "Evergreen Mechanical", JobTitle = "Sales Manager", Email = "mwilson@evergreenmech.com", Phone = "917-245-7975", Street = "208 Jackson St", City = "San Jose", PostalCode = "95112", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/michellewilson.jpg" },
			new Acquaintance() { FirstName = "Jennifer", LastName = "Gillespie", Company = "Peninsula University", JobTitle = "Superintendent", Email = "jgillespie@peninsula.org", Phone = "831-427-6746", Street = "10002 N De Anza Blvd", City = "Cupertino", PostalCode = "95014", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/jennifergillespie.jpg" },
			new Acquaintance() { FirstName = "Thomas", LastName = "White", Company = "Creative Automotive Group", JobTitle = "Service Manager", Email = "tom.white@creativeauto.com", Phone = "214-865-0771", Street = "1181 Linda Mar Blvd", City = "Pacifica", PostalCode = "94044", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/thomaswhite.jpg" },
			new Acquaintance() { FirstName = "Leon", LastName = "Muks", Company = "Spacey", JobTitle = "President", Email = "leon.muks@spacey.io", Phone = "310-586-0181", Street = "2518 Durant Ave", City = "Berkeley", PostalCode = "94704", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/leonmuks.jpg" },
			new Acquaintance() { FirstName = "Floyd", LastName = "Bell", Company = "Netcore", JobTitle = "Procurement", Email = "floyd.bell@netcore.net", Phone = "603-226-4115", Street = "450 15th St", City = "Oakland", PostalCode = "94612", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/floydbell.jpg" },
			new Acquaintance() { FirstName = "Vanessa", LastName = "Thornton", Company = "Total Sources", JobTitle = "Product Manager", Email = "vanessa.thornton@totalsourcesinc.com", Phone = "419-998-6611", Street = "550 Quarry Rd", City = "San Carlos", PostalCode = "94070", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/vanessathornton.jpg" },
			new Acquaintance() { FirstName = "John", LastName = "Boone", Company = "A. L. Price", JobTitle = "Executive Associate", Email = "jboone@alpricellc.com", Phone = "973-579-4610", Street = "233 E Harris Ave", City = "South San Francisco", PostalCode = "94080", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/johnboone.jpg" },
			new Acquaintance() { FirstName = "Ann", LastName = "Temple", Company = "Foxmoor", JobTitle = "Director", Email = "ann.temple@foxmoorinc.com", Phone = "608-821-7667", Street = "1270 San Pablo Ave", City = "Berkeley", PostalCode = "94706", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/anntemple.jpg" },
			new Acquaintance() { FirstName = "Joseph", LastName = "Meeks", Company = "Rose Records", JobTitle = "Manager", Email = "jmeeks@roserecordsllc.com", Phone = "978-628-6826", Street = "28 N 1st St", City = "San Jose", PostalCode = "95113", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/josephmeeks.jpg" },
			new Acquaintance() { FirstName = "Michelle", LastName = "Herring", Company = "Full Color", JobTitle = "Production Specialist", Email = "michelle.herring@fullcolorus.com", Phone = "201-319-9344", Street = "213 2nd Ave", City = "San Mateo", PostalCode = "94401", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/michelleherring.jpg" },
			new Acquaintance() { FirstName = "Daniel", LastName = "Jones", Company = "Flexus", JobTitle = "Quality Assurance Associate", Email = "daniel.jones@flexusinc.com", Phone = "228-432-8712", Street = "850 Bush St", City = "San Francisco", PostalCode = "94108", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/danieljones.jpg" },
			new Acquaintance() { FirstName = "Margaret", LastName = "Cargill", Company = "Redwood City Medical Group", JobTitle = "Director", Email = "mcargill@rcmg.org", Phone = "208-816-9793", Street = "1037 Middlefield Road", City = "Redwood City", PostalCode = "94063", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/margaretcargill.jpg" },
			new Acquaintance() { FirstName = "Benjamin", LastName = "Jones", Company = "JH Manufacturing", JobTitle = "Head of Manufacturing", Email = "ben.jones@jh.com", Phone = "505.562.3086", Street = "2091 Cowper St", City = "Palo Alto", PostalCode = "94306", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/benjaminjones.jpg" },
			new Acquaintance() { FirstName = "Ivan", LastName = "Diaz", Company = "XYZ Robotics", JobTitle = "CEO", Email = "ivan.diaz@xyzrobotics.com", Phone = "406-496-8774", Street = "1960 Mandela Parkway", City = "Oakland", PostalCode = "94607", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/ivandiaz.jpg" },
			new Acquaintance() { FirstName = "Eric", LastName = "Grant", Company = "MMSRI, Inc.", JobTitle = "Senior Manager", Email = "egrant@mmsri.com", Phone = "360-693-2388", Street = "2043 Martin Luther King Jr. Way", City = "Berkeley", PostalCode = "94704", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/ericgrant.jpg" },
			new Acquaintance() { FirstName = "Stacey", LastName = "Valdovinos", Company = "Global Manufacturing", JobTitle = "CEO", Email = "svaldovinos@globalmanuf.com", Phone = "440-243-7987", Street = "98 Udayakavi Lane", City = "Danville", PostalCode = "94526", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/staceyvaldovinos.jpg" },
			new Acquaintance() { FirstName = "Jesus", LastName = "Cardell", Company = "Pacific Marine Supply", JobTitle = "Manager", Email = "jcardella@pacificmarine.com", Phone = "410-745-5521", Street = "1008 Rachele Road", City = "Walnut Creek", PostalCode = "94597", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/jesuscardell.jpg" },
			new Acquaintance() { FirstName = "Wilma", LastName = "Woolley", Company = "Mission School District", JobTitle = "Superintendent", Email = "wwoolley@missionsd.org", Phone = "940-696-1852", Street = "7277 Moeser Lane", City = "El Cerrito", PostalCode = "94530", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/wilmawoolley.jpg" },
			new Acquaintance() { FirstName = "Evan", LastName = "Armstead", Company = "City of Richmond", JobTitle = "Board Member", Email = "evan.armstead@richmond.org", Phone = "415-336-2228", Street = "398 23rd St", City = "Richmond", PostalCode = "94804", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/evanarmstead.jpg" },
			new Acquaintance() { FirstName = "James", LastName = "Jones", Company = "East Bay Commercial Bank", JobTitle = "Manager", Email = "james.jones@eastbaybank.com", Phone = "313-248-7644", Street = "4501 Pleasanton Way", City = "Pleasanton", PostalCode = "94556", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/jamesjones.jpg" },
			new Acquaintance() { FirstName = "Douglas", LastName = "Greenly", Company = "Bay Tech Credit Union", JobTitle = "Vice President", Email = "d.greenly@baytechcredit.com", Phone = "201-929-0094", Street = "2267 Alameda Ave", City = "Alameda", PostalCode = "94501", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/douglasgreenly.jpg" },
			new Acquaintance() { FirstName = "Brent", LastName = "Mason", Company = "Rockridge Hotel", JobTitle = "Concierge", Email = "brent.mason@rockridgehotel.com", Phone = "940-482-7759", Street = "1960 Mandela Parkway", City = "Oakland", PostalCode = "94607", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/brentmason.jpg" },
			new Acquaintance() { FirstName = "Richard", LastName = "Hogan", Company = "Marin Luxury Senior Living", JobTitle = "Customer Care", Email = "rhogan@marinseniorliving.com", Phone = "978-658-7545", Street = "674 Tiburon Blvd", City = "Belvedere Tiburon", PostalCode = "94920", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/richardhogan.jpg" },
			new Acquaintance() { FirstName = "Daniel", LastName = "Granville", Company = "Cityview Consulting", JobTitle = "Consultant", Email = "dgranville@cityviewconsulting.com", Phone = "330-616-7467", Street = "300 Spencer Ave", City = "Sausalito", PostalCode = "94965", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/danielgranville.jpg" },
			new Acquaintance() { FirstName = "Margaret", LastName = "Kidd", Company = "Marin Cultural Center", JobTitle = "President", Email = "mkidd@marincultural.org", Phone = "406-784-0602", Street = "106 Throckmorton Ave", City = "Mill Valley", PostalCode = "94941", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/margaretkidd.jpg" },
			new Acquaintance() { FirstName = "Leo", LastName = "Parson", Company = "San Rafel Chamber of Commerce", JobTitle = "Board Member", Email = "leo.parson@sanrafaelcoc.org", Phone = "773-991-5214", Street = "199 Clorinda Ave", City = "San Rafael", PostalCode = "94901", State = "CA", PhotoUrl = "https://acquaint.blob.core.windows.net/images/leoparson.jpg" },
		};
	}
}


================================================
FILE: azure/cogs/emotion.workbook/index.workbook
================================================
---
uti: com.xamarin.workbook
platforms:
- iOS
packages:
- id: Newtonsoft.Json
  version: 8.0.3
- id: Microsoft.Net.Http
  version: 2.2.29
- id: Microsoft.ProjectOxford.Emotion
  version: 1.0.331.1
- id: Microsoft.ProjectOxford.Common
  version: 1.0.308
- id: Microsoft.Bcl.Build
  version: 1.0.21
- id: Microsoft.Bcl
  version: 1.1.10
---

# Azure Cognitive Services

Image analysis with the Cognitive Services' `EmotionServiceClient`

> ⚠️  Visit [Microsoft Cognitive Services](https://www.microsoft.com/cognitive-services) and get a key before you begin.


```csharp
var emotionKey = "YOUR_EMOTION_SERVICE_KEY_HERE";
```

Start by adding the `Microsoft.ProjectOxford.Emotion` NuGet to the iOS Workbook.
The required references are loaded into the workbook below:

```csharp
#r "System.Collections"
#r "System.IO"
#r "System.Runtime"
#r "System.Threading.Tasks"
#r "System.Net.Http"
#r "System.Net.Http.Primitives"
#r "System.Net.Http.Extensions"
#r "Newtonsoft.Json"
#r "Microsoft.ProjectOxford.Common"
#r "Microsoft.ProjectOxford.Emotion"
```

We first define a simple data structure to model an employee. Remote properties will be populated from Azure. We define a couple of local properties as well that we’ll need later.

```csharp
using Newtonsoft.Json;

public class Acquaintance
{
	public string FirstName { get; set; }
	public string LastName { get; set; }
	public string Company { get; set; }
	public string JobTitle { get; set; }
	public string Email { get; set; }
	public string Phone { get; set; }
	public string Street { get; set; }
	public string City{ get; set; }
	public string PostalCode { get; set; }
	public string State { get; set; }
	public string PhotoUrl { get; set; }
	public override string ToString () {
		return $"{FirstName} {LastName} ({JobTitle}) " + (AvatarImage == null?"⚪️":"☑️");
	}
	// client-local properties
	[JsonIgnore] public float Happiness { get; set; }
	[JsonIgnore] public UIImage AvatarImage { get; set; }
}
```

The list is populated from another sample’s [seed data](https://github.com/xamarinhq/app-acquaint/blob/2ca9e83c8344d35288e4ea7868ea6e5795a25e9c/App/Common/Acquaint.Data/SeedData.cs).

```csharp
#load "employees.csx"

var employees = SeedData.Get();
```

Here we fetch the avatar images for each person and cache them back on the model object. Inspecting the `employees` list now shows happy faces!

```csharp
foreach (var employee in employees) {
	var imageData = NSData.FromUrl (new NSUrl (employee.PhotoUrl));
	if (imageData != null)
		employee.AvatarImage = UIImage.LoadFromData (imageData);
}

employees
```

## Cognitive Services

For some real fun, we can analyze employee emotions using the Emotions API from [Microsoft Cognitive Services](https://www.microsoft.com/cognitive-services).

To test the process, analyze the first employee’s emotions in their avatar photo.
The Emotion service will fetch the avatar from a URL in this case, but it can also process raw image data sent directly from the client.

```csharp
using System.IO;
using Microsoft.ProjectOxford.Emotion;

var emotionClient = new EmotionServiceClient (emotionKey);
await emotionClient.RecognizeAsync (employees.First ().PhotoUrl)
```

The Emotion API provides an estimation of overall happiness. Perform the same analysis for all the employees and record their happiness. If the service cannot detect a human face, it will return no scores.

```csharp
foreach (var employee in employees) {
	var emotionData = await emotionClient.RecognizeAsync (employee.PhotoUrl);
	employee.Happiness = (emotionData.FirstOrDefault ()?.Scores?.Happiness).GetValueOrDefault ();
}

employees
```

We want our least happy employees to show up first...

```csharp
employees = employees.OrderBy (x => x.Happiness).ToList ()
```

## Bringing it together on iOS

The data can be rendered in a UITableView, to interact with live in the iOS simulator.

```csharp
class EmployeeTableSource : UITableViewDataSource
{
    List<Acquaintance> employees;
    public EmployeeTableSource (List<Acquaintance> emps)
    { employees = emps; }
	public override nint RowsInSection (UITableView tableview, nint section)
		=> employees.Count;

	public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
	{
		var employee = employees [indexPath.Row];

		string emoji;

		if (employee.Happiness >= 0.9) {
			emoji = "😀";
		} else if (employee.Happiness >= 0.8) {
			emoji = "🙂";
		} else if (employee.Happiness >= 0.4) {
			emoji = "😕";
		} else if (employee.Happiness == 0) {
			emoji = "🐶";
		} else {
			emoji = "😡";
		}

		return new UITableViewCell (UITableViewCellStyle.Subtitle, "MyTableCell") {
			TextLabel  = { Text = $"{employee.FirstName} {employee.LastName}" },
			DetailTextLabel = { Text = $"{employee.Happiness:P} {emoji}" },
			ImageView = { Image = employee.AvatarImage }
		};
	}
}
```

To actually render on the simulator, set the the root view controller:

```csharp
KeyWindow.RootViewController = new UINavigationController (new UITableViewController {
	Title = "Happiness Training Candidates",
	TableView = { DataSource = new EmployeeTableSource (employees) }
})
```

### Exercises

* Change the background color of the `UITableViewCell` based on the happiness of the employee.

* The Emotions API covers more than just happiness. Try adding information about anger, available in `emotionData`.

* Implement a custom `UITableViewCell` that shows all emotion data.


================================================
FILE: azure/cogs/meta.json
================================================
{
  "order":{
    "emotion.workbook":"Emotion Service"
  }
}


================================================
FILE: azure/meta.json
================================================
{
  "order":{
    "tryazure":"Try Azure",
    "cogs":"Cognitive Services"
  }
}


================================================
FILE: azure/tryazure/TryAzure-Mac.workbook
================================================
---
uti: com.xamarin.workbook
platform: MacNet45
packages:
- id: Newtonsoft.Json
  version: 9.0.1
- id: Microsoft.Net.Http
  version: 2.2.29
- id: Microsoft.Azure.Mobile.Client
  version: 3.0.1
- id: Microsoft.Bcl
  version: 1.1.10
---

# Azure TryAppService

Two NuGets - **Microsoft.Azure.Mobile.Client** & Newtonsoft.Json - have been added and require these references:

```csharp
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Mobile"
#r "Microsoft.WindowsAzure.Mobile.Ext"
```

Use the [tryappservice.azure.com](https://tryappservice.azure.com/ "tryappservice.azure.com") **Mobile App > TodoList** to create a free back-end to test. This class matches the mobile app backend that is automatically created:

```csharp
using Newtonsoft.Json;
using Microsoft.WindowsAzure.MobileServices;

public class TodoItem
{
    [JsonProperty(PropertyName = "id")]
    public string ID {get;set;}
    [JsonProperty(PropertyName = "text")]
    public string Name {get;set;}
    [JsonProperty(PropertyName = "complete")]
    public bool Done {get;set;}
    [Version]
    public string Version { get; set; }
	public override string ToString() {
		return $"{Name} is " + (Done?"done":"not done");
	}
}
```

Replace the URL below with your temporary, generated endpoint URL:

```csharp
var mobileService = new MobileServiceClient ("https://da0cfa57-0ee0-4-231-b9ee.azurewebsites.net/");
var table = mobileService.GetTable<TodoItem> ();
```

Now it’s possible to interact with the **Azure App Service**. The following code creates a new `TodoItem` class, inserts it into the table on the server, and retrieves the list from the server:

```csharp
var rememberTo = new TodoItem {Name="buy apples"};
await table.InsertAsync (rememberTo);
List<TodoItem> todos = await table.Take (10).ToListAsync ();
```





================================================
FILE: azure/tryazure/TryAzure-WPF.workbook
================================================
---
uti: com.xamarin.workbook
platform: WPF
packages:
- id: Microsoft.Bcl
  version: 1.1.10
- id: Newtonsoft.Json
  version: 9.0.1
- id: Microsoft.Net.Http
  version: 2.2.29
- id: Microsoft.Azure.Mobile.Client
  version: 3.0.1
---

# Azure TryAppService

Two NuGets - **Microsoft.Azure.Mobile.Client** & Newtonsoft.Json - have been added and require these references:

```csharp
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Mobile"
#r "Microsoft.WindowsAzure.Mobile.Ext"
```

Use the [tryappservice.azure.com](https://tryappservice.azure.com/ "tryappservice.azure.com") **Mobile App > TodoList** to create a free back-end to test. This class matches the mobile app backend that is automatically created:

```csharp
using Newtonsoft.Json;
using Microsoft.WindowsAzure.MobileServices;

public class TodoItem
{
    [JsonProperty(PropertyName = "id")]
    public string ID {get;set;}
    [JsonProperty(PropertyName = "text")]
    public string Name {get;set;}
    [JsonProperty(PropertyName = "complete")]
    public bool Done {get;set;}
    [Version]
    public string Version { get; set; }
	public override string ToString() {
		return $"{Name} is " + (Done?"done":"not done");
	}
}
```

Replace the URL below with your temporary, generated endpoint URL:

```csharp
var mobileService = new MobileServiceClient ("https://da0cfa57-0ee0-4-231-b9ee.azurewebsites.net/");
var table = mobileService.GetTable<TodoItem> ();
```

Now it’s possible to interact with the **Azure App Service**. The following code creates a new `TodoItem` class, inserts it into the table on the server, and retrieves the list from the server:

```csharp
var rememberTo = new TodoItem {Name="buy apples"};
await table.InsertAsync (rememberTo);
List<TodoItem> todos = await table.Take (10).ToListAsync ();
```



================================================
FILE: azure/tryazure/TryAzure-iOS.workbook
================================================
---
uti: com.xamarin.workbook
platform: iOS
packages:
- id: Microsoft.Bcl
  version: 1.1.10
- id: Microsoft.Net.Http
  version: 2.2.29
- id: Microsoft.Azure.Mobile.Client
  version: 3.0.1
- id: Newtonsoft.Json
  version: 9.0.1
---

# Azure TryAppService

Two NuGets - **Microsoft.Azure.Mobile.Client** & Newtonsoft.Json - have been added and require these references:

```csharp
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Mobile"
#r "Microsoft.WindowsAzure.Mobile.Ext"
```

Use the [tryappservice.azure.com](https://tryappservice.azure.com/ "tryappservice.azure.com") **Mobile App > TodoList** to create a free back-end to test. This class matches the mobile app backend that is automatically created:

```csharp
using Newtonsoft.Json;
using Microsoft.WindowsAzure.MobileServices;

public class TodoItem
{
    [JsonProperty(PropertyName = "id")]
    public string ID {get;set;}
    [JsonProperty(PropertyName = "text")]
    public string Name {get;set;}
    [JsonProperty(PropertyName = "complete")]
    public bool Done {get;set;}
    [Version]
    public string Version { get; set; }
	public override string ToString() {
		return $"{Name} is " + (Done?"done":"not done");
	}
}
```

Replace the URL below with your temporary, generated endpoint URL:

```csharp
var mobileService = new MobileServiceClient ("https://da0cfa57-0ee0-4-231-b9ee.azurewebsites.net/");
var table = mobileService.GetTable<TodoItem> ();
```

Now it’s possible to interact with the **Azure App Service**. The following code creates a new `TodoItem` class, inserts it into the table on the server, and retrieves the list from the server:

```csharp
var rememberTo = new TodoItem {Name="buy apples"};
await table.InsertAsync (rememberTo);
List<TodoItem> todos = await table.Take (10).ToListAsync ();
```


================================================
FILE: azure/tryazure/meta.json
================================================
{
  "order":{
    "TryAzure-iOS.workbook":"Try Azure for iOS",
    "TryAzure-Mac.workbook":"Try Azure for Mac",
    "TryAzure-WPF.workbook":"Try Azure for WPF"
  }
}


================================================
FILE: charts/meta.json
================================================
{
  "order":{
    "oxyplot":"OxyPlot",
    "xplot":"XPlot"
  }
}


================================================
FILE: charts/oxyplot/OxyPlot.workbook
================================================
---
id: ee57cfd4-3bc0-4069-952d-4fa85802fceb
uti: com.xamarin.workbook
copyright: © Copyright 2015, OxyPlot Contributors.
title: Plotting with OxyPlot
platforms:
- Console
packages:
- id: OxyPlot.Core
  version: 1.0.0
---

# Plotting with OxyPlot

```csharp
#r "OxyPlot"

using OxyPlot;
using OxyPlot.Series;
using OxyPlot.Axes;

using static System.Math;
```

## Function Series

First we create a model, and then add a data series to it.

```csharp
var plot = new PlotModel {
    Title = "Trigonometric functions",
    Subtitle = "Example using the FunctionSeries",
    PlotType = PlotType.Cartesian
};

plot.Series.Add (new FunctionSeries (
    Sin, -10, 10, 0.1, "sin(x)"));

plot.Series.Add (new FunctionSeries (
    Cos, -10, 10, 0.1, "cos(x)"));

plot.Series.Add (new FunctionSeries (
    t => 5 * Cos (t),
    t => 5 * Sin (t),
    0,
    2 * PI,
    0.1,
    "5cos(t), 5sin(t)"));
```

And finally render the result by ensuring the cell yields a `PlotModel` object as its last result.

```csharp
plot
```

## Bonus: Fun with bats!

```csharp
double batFn1 (double x) =>
    2 * Sqrt(-Abs(Abs(x) - 1) *
        Abs(3 - Abs(x)) / ((Abs(x) - 1) *
            (3 - Abs(x)))) *
    (1 + Abs(Abs(x) - 3) / (Abs(x) - 3)) *
    Sqrt(1 - Pow((x / 7), 2)) + (5 + 0.97 *
        (Abs(x - 0.5) + Abs(x + 0.5)) - 3 *
        (Abs(x - 0.75) + Abs(x + 0.75))) *
    (1 + Abs(1 - Abs(x)) / (1 - Abs(x)));

double batFn2 (double x) =>
    -3 * Sqrt(1 - Pow((x / 7), 2)) *
    Sqrt(Abs(Abs(x) - 4) / (Abs(x) - 4));

double batFn3 (double x) =>
    Abs(x / 2) - 0.0913722 *
    (Pow(x, 2)) - 3 + Sqrt(1 - Pow((Abs(Abs(x) - 2) - 1), 2));

double batFn4 (double x) =>
    (2.71052 + (1.5 - .5 * Abs(x)) - 1.35526 *
    Sqrt(4 - Pow((Abs(x) - 1), 2))) *
    Sqrt(Abs(Abs(x) - 1) / (Abs(x) - 1)) + 0.9;

var plot = new PlotModel { Title = "Fun with Bats" };
plot.Series.Add (new FunctionSeries (batFn1, -8, 8, 0.0001)); 
plot.Series.Add (new FunctionSeries (batFn2, -8, 8, 0.0001)); 
plot.Series.Add (new FunctionSeries (batFn3, -8, 8, 0.0001)); 
plot.Series.Add (new FunctionSeries (batFn4, -8, 8, 0.0001));

plot;
```

## Heat Map Series

```csharp
var plot = new PlotModel { Title = "Heatmap" };

// Color axis (the X and Y axes are generated automatically)

plot.Axes.Add(new LinearColorAxis {
    Palette = OxyPalettes.Rainbow(100)
});

// generate 1d normal distribution
var singleData = new double[100];
for (int x = 0; x < 100; ++x)
    singleData[x] = Exp ((-1.0 / 2.0) *
        Pow (((double)x - 50.0) / 20.0, 2.0));

// generate 2d normal distribution
var data = new double[100, 100];
for (int x = 0; x < 100; ++x) {
    for (int y = 0; y < 100; ++y)
        data[y, x] = singleData[x] *
            singleData[(y + 30) % 100] *
            100;
}

var heatMapSeries = new HeatMapSeries {
    X0 = 0,
    X1 = 99,
    Y0 = 0,
    Y1 = 99,
    Interpolate = true,
    RenderMethod = HeatMapRenderMethod.Bitmap,
    Data = data
};

plot.Series.Add (heatMapSeries);

plot;
```

> ℹ️ This workbook was adapted from the official [OxyPlot documentation](http://docs.oxyplot.org/en/latest/).

================================================
FILE: charts/oxyplot/meta.json
================================================
{
  "order":{
    "OxyPlot.workbook":"Get Started with OxyPlot"
  }
}


================================================
FILE: charts/xplot/XPlot.workbook
================================================
---
uti: com.xamarin.workbook
id: 036795c2-a071-4ad5-9375-d0c82482d37d
title: XPlot
platforms:
- Console
packages:
- id: XPlot.Plotly
  version: 1.4.2
---

```csharp
#r "XPlot.Plotly"
```

# Plotly Example

Random data, 3D scatter plot.

```csharp
using XPlot.Plotly;

var traces = new List<Graph.Scatter3d>();

var rnd = new Random();

(List<double> x, List<double> y, List<double> z) GenerateNumbers (int count) {
    var x = new List<double>();
    var y = new List<double>();
    var z = new List<double>();
    for (int digit = 0; digit < count; digit ++)
    {
        x.Add(rnd.NextDouble()*50);
        y.Add(rnd.NextDouble()*50);
        z.Add(rnd.NextDouble()*50);
    }
    return (x, y, z);
}

for (int i = 0; i < 3; i++) {
    var (x, y, z) = GenerateNumbers (25);

    string randomcolor = $"rgb({rnd.Next(50, 200)},{rnd.Next(50, 200)},{rnd.Next(50, 200)})";
    var trace = new Graph.Scatter3d() {
        x = x,
        y = y,
        z = z,
        mode = "markers", 
        marker = new Graph.Marker() {
            color = randomcolor,
            size = 5.0,
            symbol = "circle", 
            line = new Graph.Line() {
                color = "rgb(0,0,0)",
                width = 0.0
            }
        },
        line = new Graph.Line() {
            color = "#1f77b4",
            width = 1.0
        }
    };
    traces.Add(trace);
}

var layout = new Layout.Layout() {
    title = "Dots In Space",
    autosize = false,   
    margin = new Graph.Margin() {
           l = 0, r = 0, b = 0, t = 65
    }
}; 
var scatterplot = Chart.Plot(traces.ToArray(), layout);

scatterplot.WithWidth(800); 
scatterplot.WithHeight(500);
scatterplot
```

================================================
FILE: charts/xplot/meta.json
================================================
{
  "order":{
    "XPlot.workbook":"Get Started with XPlot"
  }
}


================================================
FILE: csharp/async/README.md
================================================
Async-Await Workbook
=========

A simple `callback` versus `await` demo related to 
[Xamarin's async support overview](https://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/).


![](Screenshots/async.png)


================================================
FILE: csharp/async/async-await-wpf.workbook
================================================
---
uti: com.xamarin.workbook
platform: WPF
packages: []
---


# Async 101

A quick explanation of why `async-await` code is easier to read/follow
than old-style callbacks. Read more at
[Xamarin's async support overview](https://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/).


## The Old Way - Callbacks

1. Get all the config out of the way

```csharp
var webClient = new System.Net.WebClient();
webClient.Encoding = System.Text.Encoding.UTF8;

var xmlUri = new Uri("http://api.geonames.org/earthquakesXML?north=44.1&south=-9.9&east=-22.4&west=55.2&username=bertt");
```

2. We have to set up the 'callback' handler which is called
when the network operation completes

```csharp
var response1 = "";
webClient.DownloadStringCompleted += (s, e) => {
    response1 = e.Result; // get the downloaded text
};
webClient.DownloadStringAsync(xmlUri);
```

3. *Then* we call the actual method - confusing huh? The code we just wrote
above gets executed *after* this completes!

```csharp
// this will be blank because the completed even won't have fired in most cases
// type `response1` in the interactive window to confirm that the XML was downloaded
response1
```

(we'll check on the response later)

## The New Way - Async

1. Get all the config out of the way

```csharp
#r "System.Net.Http"
```

```csharp
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;

var jsonUri = "http://api.geonames.org/earthquakesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&username=bertt";
```

2. The network call code is in a logical place

```csharp
var response2 = await new HttpClient().GetStringAsync(jsonUri);
```

3. *Then* we do something with the result - much easier to follow
what's happening in the code!

```csharp
Console.WriteLine(response2.Substring(0,100) + "...");
```

## Finally...

Check `response1` from the first example again - the completed callback
has probably been executed by now...

```csharp
response1
```


================================================
FILE: csharp/async/async-await.workbook
================================================
---
uti: com.xamarin.workbook
platforms:
- MacNet45
---

# Async 101

A quick explanation of why `async-await` code is easier to read/follow
than old-style callbacks. Read more at
[Xamarin's async support overview](https://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/).

## The Old Way - Callbacks

1. Get all the config out of the way

```csharp
var webClient = new System.Net.WebClient();
webClient.Encoding = System.Text.Encoding.UTF8;

var xmlUri = new Uri("http://api.geonames.org/earthquakesXML?north=44.1&south=-9.9&east=-22.4&west=55.2&username=bertt");
```

1. We have to set up the 'callback' handler which is called
   when the network operation completes

```csharp
var response1 = "";
webClient.DownloadStringCompleted += (s, e) => {
    response1 = e.Result; // get the downloaded text
};
webClient.DownloadStringAsync(xmlUri);
```

1. *Then* we call the actual method - confusing huh? The code we just wrote
   above gets executed *after* this completes!

```csharp
// this will be blank because the completed even won't have fired in most cases
// type `response1` in the interactive window to confirm that the XML was downloaded
response1
```

\(we'll check on the response later)

## The New Way - Async

1. Get all the config out of the way

```csharp
#r "System.Net.Http"
```

```csharp
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;

var jsonUri = "http://api.geonames.org/earthquakesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&username=bertt";
```

1. The network call code is in a logical place

```csharp
var response2 = await new HttpClient().GetStringAsync(jsonUri);
```

1. *Then* we do something with the result - much easier to follow
   what's happening in the code!

```csharp
Console.WriteLine(response2.Substring(0,100) + "...");
```

## Finally...

Check `response1` from the first example again - the completed callback
has probably been executed by now...

```csharp
response1
```

================================================
FILE: csharp/async/meta.json
================================================
{
  "order":{
    "async-await.workbook":"Async Await",
    "async-await-wpf.workbook":"Async Await for WPF"
  }
}


================================================
FILE: csharp/collections/README.md
================================================
Collections: Arrays Workbook
=========

Quick explanation of how C# arrays work.


![](Screenshots/arrays.png)


================================================
FILE: csharp/collections/arrays.workbook
================================================
---
uti: com.xamarin.workbook
platforms:
- Console
---

# Collections: Arrays

An array is a simple data structure:

* it stores a collection of data elements,
* it has a fixed size,
* it only contains elements that match the declared type.

## Initialization Syntax

The easiest way to create an array with known values
is using C#'s initialization syntax:

```csharp
int[] primes = {2,3,5,7,11,13,17,19,31,37,41,43,47,53,59,61,67,71}
```

Each value in the array has an `index`, and we can get a value
by its index:

```csharp
primes[9] // prints the 10th prime - arrays are zero-based!
```

## Create a fixed size array

Another way to create an array is to declare the array
with a known size (20 elements in this example), and
then set each value using the index (remember it starts at zero):

```csharp
var squares = new int[20]; // 20 elements with default(int) value
for (var i = 0; i <20; i++) {
	squares[i] = i*i;
}

squares
```

The values in the array can then be retrieved by their index:

```csharp
squares[4] // 5th square
```

The value at an index can also be set to a different value:

```csharp
squares[4] = 444 // replace the value in index '4'
```

## Declare and then set

If the size of the array is initially unknown, an
array variable can be declared without specifying the size.

```csharp
string[] dwarves;
// ...
dwarves = new string[4];
dwarves[0] = "Sleepy";
dwarves[1] = "Sneezy";
dwarves[2] = "Dopey";
dwarves[3] = "Doc";

dwarves
```

This highlights a problem with arrays – once the
size has been declared, we can't easily change it
to add another three dwarves:

`dwarves[4] = "Bashful"`

will result in an `IndexOutOfRangeException`. The only
option is to assign a totally new array to the variable:

```csharp
dwarves = new string[7];
dwarves[0] = "Sleepy";
dwarves[1] = "Sneezy";
dwarves[2] = "Dopey";
dwarves[3] = "Doc";
dwarves[4] = "Bashful";
dwarves[5] = "Grumpy";
dwarves[6] = "Happy";

dwarves
```

## Not just simple Types

Arrays can also store objects, not just `string` and `int`:

```csharp
class Person {
  public string FirstName {get;set;}
  public string LastName {get;set;}
  public override string ToString() => $"{FirstName} {LastName}";
}
var goodguys = new Person[2];
goodguys[0] = new Person {FirstName="Snow",LastName="White"};
goodguys[1] = new Person {FirstName="Humbert",LastName="Huntsman"};
```

```csharp
goodguys // view the array data
```

## Pros & Cons of Arrays

### Pros

* Simple and easy to understand
* Fast and efficient

### Cons

* Cannot be resized
* Elements cannot be added or removed

Other collection types like `List` and `Dictionary` address some
of the array's limitations.


================================================
FILE: csharp/collections/meta.json
================================================
{
  "order":{
    "arrays.workbook":"Arrays"
  }
}


================================================
FILE: csharp/csharp6/README.md
================================================
C# 6 Workbook
=========

A smattering of C# 6 syntax examples from this
[C# 6 overview](https://developer.xamarin.com/guides/cross-platform/advanced/csharp_six/).

![](Screenshots/csharp6.png)


================================================
FILE: csharp/csharp6/csharp6.workbook
================================================
---
uti: com.xamarin.workbook
platforms:
- Console
---

# Using C# 6

Some examples from Xamarin's [intro to C# 6](https://developer.xamarin.com/guides/cross-platform/advanced/csharp_six/).

* Null-conditional operator

* String Interpolation

* Expression-bodied Function Members

* Auto-property Initialization

* Index Initializers

* using static

## Null-conditional operator

The `?.` operator automatically does a null-check before referencing the
specified member. The example string array below has a `null` entry:

```csharp
var names = new string[] { "Foo", null };
```

In C# 5, a null-check is required before accessing the `.Length` property:

```csharp
// C# 5
int secondLength = 0;
if (names[1] != null)
  secondLength = names[1].Length;
```

C# 6 allows the length to be queried in a single line; the entire
statement returns `null` if any object is null.

```csharp
var length0 = names[0]?.Length; // 3
var length1 = names[1]?.Length; // null
```

This can be used in conjunction with the `??` null coalescing operator
to set a default value (such as `0`) in the example below:

```csharp
var lengths = names.Select (names => names?.Length ?? 0); //[3, 0]
```

## String Interpolation

Previously strings were built in a number of different ways:

```csharp
var animal = "Monkeys";
var food = "bananas";

var out1 = String.Format ("{0} love to eat {1}", animal, food);
var out2 = animal + " love to eat " + food;
// or even StringBuilder
```

C# 6 provides a simple syntax where the fieldname can be
embedded directly in the string:

```csharp
$"{animal} love to eat {food}"
```

String-formatting can also be done with this syntax:

```csharp
var values = new int[] { 1, 2, 3, 4, 12, 123456 };
foreach (var s in values.Select (i => $"The value is {i,10:N2}.")) {
   Console.WriteLine (s);
}
```

## Expression-bodied Function Members

The `ToString` override in the following class is an expression-bodied
function - a more succinct declaration syntax.

```csharp
class Person
{
    public string FirstName { get; }
    public string LastName { get; }
    public Person (string firstname, string lastname)
    {
       FirstName = firstname;
       LastName = lastname;
    }
    // note there is no explicit `return` keyword
    public override string ToString () => $"{LastName}, {FirstName} {LastName}";
}
```

`void` expression bodied functions are also allowed so long as
the expression is a statement:

```csharp
public void Log(string message) => System.Console.WriteLine($"{DateTime.Now.ToString ("s", System.Globalization.CultureInfo.InvariantCulture )}: {message}");
```

This simple example calls these two methods:

```csharp
Log(new Person("James", "Bond").ToString())
```

## Auto-property Initialization

Properties (ie. specified with `{get;set;}`) can be initialized inline
with C# 6:

```csharp
class Todo
{
    public bool Done { get; set; } = false;
    public DateTime Created { get; } = DateTime.Now;
    public string Description { get; }

    public Todo (string description)
    {
       this.Description = description; // can assign (only in constructor!)
    }
    public override string ToString () => $"'{Description}' was created on {Created}";
}
```

```csharp
new Todo("buy apples")
```

## Index Initializers

Dictionary-style data structures let you specify key/value
types with a simple object-initializer-like syntax:

```csharp
var userInfo = new Dictionary<string,object> {
    ["Created"] = DateTime.Now,
    ["Due"] = DateTime.Now.AddSeconds(60 * 60 * 24),
    ["Task"] = "buy lettuce"
};
```

## using static

Enumerations, and certain classes such as System.Math, are primarily
holders of static values and functions. In C# 6, you can import all
static members of a type with a single using static statement:

```csharp
using static System.Math;
```

C# 6 code can then reference the static members directly, avoiding
repetition of the class name (eg. `Math.PI` becomes `PI`):

```csharp
public class Location 
{
    public Location (double lat, double @long) {Latitude = lat; Longitude = @long;} 
    public double Latitude = 0; public double Longitude = 0; 
}
static public double MilesBetween(Location loc1, Location loc2)
{
  double rlat1  = PI * loc1.Latitude / 180;
  double rlat2  = PI * loc2.Latitude / 180;
  double theta  = loc1.Longitude - loc2.Longitude;
  double rtheta = PI * theta / 180;
  double dist =
      Sin(rlat1) * Sin(rlat2) + Cos(rlat1) *
      Cos(rlat2) * Cos(rtheta);
  dist = Acos(dist);
  dist = dist*180/PI;
  dist = dist*60*1.1515;
  return dist; //miles
}
```

```csharp
MilesBetween (new Location(-12,22), new Location(-13,33))
```

================================================
FILE: csharp/csharp6/meta.json
================================================
{
  "order":{
    "csharp6.workbook":"Using C# 6"
  }
}


================================================
FILE: csharp/csharp7/csharp7.workbook
================================================
---
uti: com.xamarin.workbook
title: What's New in C# 7 | C# Guide
platforms:
- Console
---

> ⚠️ C# 7 is supported in Xamarin Workbooks 1.2 (or newer).
> Please update to version 1.2 if you experience issues with this Workbook (you may need to switch to the Alpha or Beta channel).

# What's new in C# 7

C# 7 adds a number of new features to the C# language:

* `out` variables

  * You can declare `out` values inline as arguments to the method where they are used.

* Tuples

  * You can create lightweight, unnamed types that contain multiple public fields. Compilers and IDE tools understand the semantics of these types.

* Pattern Matching

  * You can create branching logic based on arbitrary types and values of the members of those types.

* `ref` locals and returns

  * Method arguments and local variables can be references to other storage.

* Local Functions

  * You can nest functions inside other functions to limit their scope and visibility.

* More expression-bodied members

  * The list of members that can be authored using expressions has grown.

* `throw` Expressions

  * You can throw exceptions in code constructs that previously were not allowed because `throw` was a statement.

* Generalized async return types

  * Methods declared with the `async` modifier can return other types in addition to `Task` and `Task<T>`.

* Numeric literal syntax improvements

  * New tokens improve readability for numeric constants.

The remainder of this topic discusses each of the features. For each feature, you'll learn the reasoning behind it. You'll learn the syntax. You'll see some sample scenarios where using the new feature will make you more productive as a developer.

## `out` variables

The existing syntax that supports `out` parameters has been improved in this version.

Previously, you would need to separate the declaration of the out variable and its initialization into two different statements:

```csharp
var input = "8675309";

int numericResult;
if (int.TryParse(input, out numericResult))
    Console.WriteLine(numericResult);
else
    Console.WriteLine("Could not parse input");
```

You can now declare `out` variables in the argument list of a method call, rather than writing a separate declaration statement:

```csharp
if (int.TryParse(input, out int result))
    Console.WriteLine(result);
else
    Console.WriteLine("Could not parse input");
```

You may want to specify the type of the `out` variable for clarity, as shown above. However, the language does support using an implicitly typed local variable:

```csharp
if (int.TryParse(input, out var answer))
    Console.WriteLine(answer);
else
    Console.WriteLine("Could not parse input");
```

* The code is easier to read.

  * You declare the out variable where you use it, not on another line above.

* No need to assign an initial value.

  * By declaring the `out` variable where it is used in a method call, you can't accidentally use it before it is assigned.

The most common use for this feature will be the `Try` pattern. In this pattern, a method returns a `bool` indicating success or failure and an`out` variable that provides the result if the method succeeds.

## Tuples

C# provides a rich syntax for classes and structs that is used to explain your design intent. But sometimes that rich syntax requires extra work with minimal benefit. You may often write methods that need a simple structure containing more than one data element. To support these scenarios *tuples* were added to C#. Tuples are lightweight data structures that contain multiple fields to represent the data members. The fields are not validated, and you cannot define your own methods

> ℹ️  Tuples were available before C# 7 as an API, but had many limitations. Most importantly, the members of these tuples were named `Item1`, `Item2` and so on. The language support enables semantic names for the fields of a Tuple.

You can create a tuple by assigning each member to a value:

```csharp
var letters = ("a", "b");
```

That assignment creates a tuple whose members are `Item1` and `Item2`, following the existing System.Tuple syntax. You can modify that assignment to create a tuple that provides semantic names to each of the members of the tuple:

```csharp
(string Alpha, string Beta) namedLetters = ("a", "b");
```

> ℹ️  The new tuples features require the `System.ValueTuple` type. For Visual Studio 15 Preview 5 and earlier preview releases, you must add the NuGet package "System.ValueTuple", available in the pre-release stream.

The `namedLetters` tuple contains fields referred to as `Alpha` and `Beta`. In a tuple assignment, you can also specify the names of the fields on the right-hand side of the assignment:

```csharp
var alphabetStart = (Alpha: "a", Beta: "b");
```

The language allows you to specify names for the fields on both the left and right-hand side of the assignment:

```csharp
(string First, string Second) firstLetters = (Alpha: "a", Beta: "b");
```

The line above generates a warning, `CS8123`, telling you that the names on the right side of the assignment, `Alpha` and `Beta` are ignored because they conflict with the names on the left side, `First` and `Second`.

The examples above show the basic syntax to declare tuples. Tuples are most useful as return types for `private` and `internal` methods. Tuples provide a simple syntax for those methods to return multiple discrete values: You save the work of authoring a `class` or a `struct` that defines the type returned. There is no need for creating a new type.

Creating a tuple is more efficient and more productive. It is a simpler, lightweight syntax to define a data structure that carries more than one value. The example method below returns the minimum and maximum values found in a sequence of integers:

```csharp
private static (int Max, int Min) Range(IEnumerable<int> numbers)
{
    int min = int.MaxValue;
    int max = int.MinValue;
    foreach(var n in numbers)
    {
        min = (n < min) ? n : min;
        max = (n > max) ? n : max;
    }
    return (max, min);
}
```

Using tuples in this way offers several advantages:

* You save the work of authoring a `class` or a `struct` that defines the type returned.

* You do not need to create new type.

* The language enhancements removes the need to call the `System.Tuple.Create<T>()` methods.

The declaration for the method provides the names for the fields of the tuple that is returned. When you call the method, the return value is a tuple whose fields are `Max` and `Min`:

```csharp
int [] numbers = { 97, 243, 254, 41, 132, 26, 167, 19, 201, 252, 119, 68, 17, 66, 131 };

var range = Range(numbers);
```

There may be times when you want to unpackage the members of a tuple that were returned from a method.  You can do that by declaring separate variables for each of the values in the tuple. This is called *deconstructing* the tuple:

```csharp
(int max, int min) = Range(numbers);
```

You can also provide a similar deconstruction for any type in .NET. This is done by writing a `Deconstruct` method as a member of the class. That `Deconstruct` method provides a set of `out` arguments for each of the properties you want to extract. Consider this `Point` class that provides a deconstructor method that extracts the `X` and `Y` coordinates:

```csharp
public class Point
{
    public Point(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public void Deconstruct(out double x, out double y)
    {
        x = this.X;
        y = this.Y;
    }
}
```

You can extract the individual fields by assigning a tuple to a `Point`:

```csharp
var p = new Point(3.14, 2.71);
(double X, double Y) = p;
```

You are not bound by the names defined in the `Deconstruct` method. You can rename the extract variables as part of the assignment:

```csharp
(double horizontalDistance, double verticalDistance) = p;
```

## Pattern matching

*Pattern matching* is a feature that allows you to implement method dispatch on properties other than the type of an object. You're probably already familiar with method dispatch based on the type of an object. In Object Oriented programming, virtual and override methods provide language syntax to implement method dispatching based on an object's type. Base and Derived classes provide different implementations. Pattern matching expressions extend this concept so that you can easily implement similar dispatch patterns for types and data elements that are not related through an inheritance hierarchy.

Pattern matching supports `is` expressions and `switch` expressions. Each enables inspecting an object and its properties to determine if that object satisfies the sought pattern. You use the `when` keyword to specify additional rules to the pattern.

### `is` expressions

The `is` pattern expressions extend the familiar `is` operator to query a object beyond its type.

Let's start with a simple scenario. We'll add capabilities to this scenario that demonstrate how pattern matching expressions make algorithms that work with unrelated types easy. We'll start with a method that computes the sum of a number of die rolls:

```csharp
public static int DiceSum(IEnumerable<int> values) => values.Sum()
```

You might quickly find that you need to find the sum of die rolls where some of the rolls are made with more than one die. Part of the input sequence may be multiple results instead of a single number:

```csharp
public static int DiceSum2(IEnumerable<object> values)
{
    var sum = 0;
    foreach(var item in values)
    {
        if (item is int val)
            sum += val;
        else if (item is IEnumerable<object> subList)
            sum += DiceSum2(subList);
    }
    return sum;
}
```

The `is` pattern expression works quite well in this scenario. As part of checking the type, you write a variable initialization. This creates a new variable of the validated runtime type.

As you keep extending these scenarios, you may find that you build more `if` and `else if` statements. Once that becomes unwieldy, you'll likely want to switch to `switch` pattern expressions.

### `switch` expressions

The `switch` pattern expression has a familiar syntax, based on the `switch` statement already part of the C# language. Let's translate the existing code to use a `switch` expression before adding new cases:

```csharp
public static int DiceSum3(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case int val:
                sum += val;
                break;
            case IEnumerable<object> subList:
                sum += DiceSum3(subList);
                break;
        }
    }
    return sum;
}
```

The `switch` expressions have a slightly different syntax than the `is` expressions, where you declare the type and variable at the beginning of the `case` expression.

The `switch` expressions also support constants. This can save time by factoring out simple cases:

```csharp
public static int DiceSum4(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case 0:
                break;
            case int val:
                sum += val;
                break;
            case IEnumerable<object> subList when subList.Any():
                sum += DiceSum4(subList);
                break;
            case IEnumerable<object> subList:
                break;
            case null:
                break;
            default:
                throw new InvalidOperationException("unknown item type");
        }
    }
    return sum;
}
```

The code above adds cases for `0` as a special case of `int`, and `null` as a special case when there is no input. This demonstrates one important new feature in switch pattern expressions: the order of the `case` expressions now matters. The `0` case must appear before the general `int` case. Otherwise, the first pattern to match would be the `int` case, even when the value is `0`.

This same behavior enables the special case for an empty input sequence. You can see that the case for an `IEnumerable` item that has elements must appear before the general `IEnumerable` case.

This version has also added a `default` case. The `default` case is always evaluated last, regardless of the order it appears in the source. For that reason, convention is to put the `default` case last.

Finally, let's add one last `case` for a new style of die. Some games use percentile dice to represent larger ranges of numbers.

> ℹ️  Two 10-sided percentile dice can represent every number from 0 through 99. One die has sides labelled `00`, `10`, `20`, ... `90`. The other die has sides labeled `0`, `1`, `2`, ... `9`. Add the two die values together and you can get every number from 0 through 99.

To add this kind of die to your collection, first define a type to represent the percentile die:

```csharp
public struct PercentileDie
{
    public int Value { get; }
    public int Multiplier { get; }

    public PercentileDie(int multiplier, int value)
    {
        this.Value = value;
        this.Multiplier = multiplier;
    }
}
```

Then, add a `case` expression for the new type:

```csharp
public static int DiceSum5(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case 0:
                break;
            case int val:
                sum += val;
                break;
            case PercentileDie die:
                sum += die.Multiplier * die.Value;
                break;
            case IEnumerable<object> subList when subList.Any():
                sum += DiceSum5(subList);
                break;
            case IEnumerable<object> subList:
                break;
            case null:
                break;
            default:
                throw new InvalidOperationException("unknown item type");
        }
    }
    return sum;
}
```

The new syntax for pattern matching expressions makes it easier to create dispatch algorithms based on an object's type, or other properties, using a clear and concise syntax. Pattern matching expressions enable these constructs on data types that are unrelated by inheritance.

## Local functions

Many designs for classes include methods that are called from only one location. These additional private methods keep each method small and focused. However, they can make it harder to understand a class when reading it the first time. These methods must be understood outside of the context of the single calling location.

For those designs, *local functions* enable you to declare methods inside the context of another method. This makes it easier for readers of the class to see that the local method is only called from the context in which is it declared.

There are two very common use cases for local functions: public iterator methods and public async methods. Both types of methods generate code that reports errors later than programmers might expect. In the case of iterator methods, any exceptions are observed only when calling code that enumerates the returned sequence. In the case of async methods, any exceptions are only observed when the returned `Task` is awaited.

Let's start with an iterator method:

```csharp
public static IEnumerable<char> AlphabetSubset(char start, char end)
{
    if ((start < 'a') || (start > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if ((end < 'a') || (end > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    for (var c = start; c < end; c++)
        yield return c;
}
```

Examine the code below that calls the iterator method incorrectly:

```csharp
var resultSet = AlphabetSubset('f', 'a');
Console.WriteLine("iterator created");
foreach (var thing in resultSet)
    Console.Write($"{thing}, ");
```

The exception is thrown when `resultSet` is iterated, not when `resultSet` is created. In this contained example, most developers could quickly diagnose the problem. However, in larger codebases, the code that creates an iterator often isn't as close to the code that enumerates the result. You can refactor the code so that the public method validates all arguments, and a private method generates the enumeration:

```csharp
public static IEnumerable<char> AlphabetSubset2(char start, char end)
{
    if ((start < 'a') || (start > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if ((end < 'a') || (end > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    return alphabetSubsetImplementation(start, end);
}

private static IEnumerable<char> alphabetSubsetImplementation(char start, char end)
{
    for (var c = start; c < end; c++)
        yield return c;
}
```

This refactored version will throw exceptions immediately because the public method is not an iterator method; only the private method uses the `yield return` syntax. However, there are potential problems with this refactoring. The private method should only be called from the public interface method, because otherwise all argument validation is skipped. Readers of the class must discover this fact by reading the entire class and searching for any other references to the `alphabetSubsetImplementation` method.

You can make that design intent more clear by declaring the `alphabetSubsetImplementation` as a local function inside the public API method:

```csharp
public static IEnumerable<char> AlphabetSubset3(char start, char end)
{
    if ((start < 'a') || (start > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if ((end < 'a') || (end > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");

    return alphabetSubsetImplementation();

    IEnumerable<char> alphabetSubsetImplementation()
    {
        for (var c = start; c < end; c++)
            yield return c;
    }
}
```

The version above makes it clear that the local method is referenced only in the context of the outer method. The rules for local functions also ensure that a developer can't accidentally call the local function from another location in the class and bypass the argument validation.

The same technique can be employed with `async` methods to ensure that exceptions arising from argument validation are thrown before the asynchronous work begins:

```csharp
public Task<string> PerformLongRunningWork(string address, int index, string name)
{
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException(message: "An address is required", paramName: nameof(address));
    if (index < 0)
        throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");
    if (string.IsNullOrWhiteSpace(name))
        throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));

    return longRunningWorkImplementation();

    async Task<string> longRunningWorkImplementation()
    {
        var interimResult = await FirstWork(address);
        var secondResult = await SecondStep(index, name);
        return $"The results are {interimResult} and {secondResult}. Enjoy.";

        Task<string> FirstWork(string x) => Task.FromResult (x);
        Task<string> SecondStep(int i, string x) => Task.FromResult ($"{x}: {i}");
    }
}
```

> ℹ️  Some of the designs that are supported by local functions could also be accomplished using *lambda expressions*.

## More expression-bodied members

C# 6 introduced expression-bodied members for member functions, and read-only properties. C# 7 expands the allowed members that can be implemented as expressions. In C# 7, you can implement *constructors*, *finalizers*, and `get` and `set` accessors on *properties* and *indexers*. The following code shows examples of each:

```csharp
class ExpressionMembersExample
{
    // Expression-bodied constructor
    public ExpressionMembersExample(string label) => this.Label = label;

    // Expression-bodied finalizer
    ~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

    private string label;

    // Expression-bodied get / set accessors.
    public string Label
    {
        get => label;
        set => this.label = value ?? "Default label";
    }
}
```

> ℹ️  This example does not need a finalizer, but it is shown to demonstrate the syntax. You should not implement a finalizer in your class unless it is necessary to  release unmanaged resources. You should also consider using the `System.Runtime.InteropServices.SafeHandle` class instead of managing unmanaged resources directly.

These new locations for expression-bodied members represent an important milestone for the C# language: These features were implemented by community members working on the open-source [Roslyn](https://github.com/dotnet/Roslyn) project.

## Throw expressions

In C#, `throw` has always been a statement. Because `throw` is a statement, not an expression, there were C# constructs where you could not use it. These included conditional expressions, null coalescing expressions, and some lambda expressions. The addition of expression-bodied members adds more locations where `throw` expressions would be useful. So that you can write any of these constructs, C# 7 introduces *throw expressions*.

The syntax is the same as you've always used for `throw` statements. The only difference is that now you can place them in new locations, such as in a conditional expression:

```csharp
class ExpressionMembersExample
{
    private string name;

    public string Name
    {
        get => name;
        set => name = value ??
            throw new ArgumentNullException(paramName: nameof(value), message: "New name must not be null");
    }
}
```

This features enables using throw expressions in initialization expressions:

```csharp
class ConfigResource { }
static ConfigResource LoadConfigResourceOrDefault () => null;

private ConfigResource loadedConfig = LoadConfigResourceOrDefault() ??
   throw new InvalidOperationException("Could not load config");
```

Previously, those initializations would need to be in a constructor, with the throw statements in the body of the constructor:

```csharp
class ApplicationOptions
{
    public ApplicationOptions()
    {
        var loadedConfig = LoadConfigResourceOrDefault();
        if (loadedConfig == null)
            throw new InvalidOperationException("Could not load config");
    }
}
```

> ℹ️  Both of the preceding constructs will cause exceptions to be thrown during the construction of an object. Those are often difficult to recover from. For that reason, designs that throw exceptions during construction are discouraged.

## Numeric literal syntax improvements

Misreading numeric constants can make it harder to understand code when reading it for the first time. This often occurs when those numbers are used as bit masks or other symbolic rather than numeric values. C# 7 includes two new features to make it easier to write numbers in the most readable fashion for the intended use: *binary literals*, and *digit separators*.

For those times when you are creating bit masks, or whenever a binary representation of a number makes the most readable code, write that number in binary:

```csharp
public const int One =  0b0001;
public const int Two =  0b0010;
public const int Four = 0b0100;
public const int Eight = 0b1000;
```

The `0b` at the beginning of the constant indicates that the number is written as a binary number.

Binary numbers can get very long, so it's often easier to see the bit patterns by introducing the `_` as a digit separator:

```csharp
public const int Sixteen =   0b0001_0000;
public const int ThirtyTwo = 0b0010_0000;
public const int SixtyFour = 0b0100_0000;
public const int OneHundredTwentyEight = 0b1000_0000;
```

The digit separator can appear anywhere in the constant. For base 10 numbers, it would be common to use it as a thousands separator:

```csharp
public const long BillionsAndBillions = 100_000_000_000;
```

The digit separator can be used with `decimal`, `float` and `double` types as well:

```csharp
public const double AvogadroConstant = 6.022_140_857_747_474e23;
public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;
```

Taken together, you can declare numeric constants with much more readability.

## Ref locals and returns

This feature enables algorithms that use and return references to variables defined elsewhere. One example is working with large matrices, and finding a single location with certain characteristics. One method would return the two indices for a single location in the matrix:

```csharp
public static (int i, int j) Find(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return (i, j);
    return (-1, -1); // Not found
}
```

There are many issues with this code. First of all, it's a public method that's returning a tuple. The language supports this, but user defined types (either classes or structs) are preferred for public APIs.

Second, this method is returning the indices to the item in the matrix. That leads callers to write code that uses those indices to dereference the matrix and modify a single element:

```csharp
var matrix = new int[,] {
    { 5, 9, 11, 4},
    { 3, 10, 18, 9},
    { 1, 19, 42, 2},
    { 0, 3, 4, 31},
};

var indices = Find(matrix, (val) => val == 42);
Console.WriteLine(indices);
matrix[indices.i, indices.j] = 24;
```

You'd rather write a method that returns a *reference* to the element of the matrix that you want to change. You could only accomplish this by using unsafe code and returning a pointer to an `int` in previous versions.

Let's walk through a series of changes to demonstrate the ref local feature and show how to create a method that returns a reference to internal storage. Along the way, you'll learn the rules of the ref return and ref local feature that protects you from accidentally misusing it.

Start by modifying the `Find` method declaration so that it returns a `ref int` instead of a tuple. Then, modify the return statement so it returns the value stored in the matrix instead of the two indices:

```csharp
// Note that this won't compile.
// Method declaration indicates ref return,
// but return statement specifies a value return.
//
// public static ref int Find2(int[,] matrix, Func<int, bool> predicate)
// {
//     for (int i = 0; i < matrix.GetLength(0); i++)
//         for (int j = 0; j < matrix.GetLength(1); j++)
//             if (predicate(matrix[i, j]))
//                 return matrix[i, j];
//     throw new InvalidOperationException("Not found");
// }
```

When you declare that a method returns a `ref` variable, you must also add the `ref` keyword to each return statement. That indicates return by reference, and helps developers reading the code later remember that the method returns by reference:

```csharp
public static ref int Find3(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return ref matrix[i, j];
    throw new InvalidOperationException("Not found");
}
```

Now that the method returns a reference to the integer value in the matrix, you need to modify where it's called.  The `var` declaration means that `valItem` is now an `int` rather than a tuple:

```csharp
var valItem = Find3(matrix, (val) => val == 42);
Console.WriteLine(valItem);
valItem = 24;
Console.WriteLine(matrix[4, 2]);
```

The second `WriteLine` statement in the example above prints out the value `42`, not `24`. The variable `valItem` is an `int`, not a `ref int`. The `var` keyword enables the compiler to specify the type, but will not implicitly add the `ref` modifier. Instead, the value referred to by the `ref return` is *copied* to the variable on the left-hand side of the assignment. The variable is not a `ref` local.

In order to get the result you want, you need to add the `ref` modifier to the local variable declaration to make the variable a reference when the return value is a reference:

```csharp
ref var item = ref Find3(matrix, (val) => val == 42);
Console.WriteLine(item);
item = 24;
Console.WriteLine(matrix[4, 2]);
```

Now, the second `WriteLine` statement in the example above will print out the value `24`, indicating that the storage in the matrix has been modified. The local variable has been declared with the `ref` modifier, and it will take a `ref` return. You must initialize a `ref` variable when it is declared, you cannot split the declaration and the initialization.

The C# language has two other rules that protect you from misusing the `ref` locals and returns:

* You cannot assign a value to a `ref` variable.

  * That disallows statements like `ref int i = sequence.Count();`

* You cannot return a `ref` to a variable whose lifetime does not extend beyond the execution of the method.

  * That means you cannot return a reference to a local variable, or similar scope.

These rules ensure that you cannot accidentally mix value variables and reference variables. They also ensure that you cannot have a reference variable refer to storage that is a candidate for garbage collection.

The addition of ref locals and ref returns enable algorithms that are more efficient by avoiding copying values, or performing dereferencing operations multiple times.


================================================
FILE: csharp/csharp7/index.workbook
================================================
---
uti: com.xamarin.workbook
title: What's New in C# 7 | C# Guide
platforms:
- Console
---

> ⚠️ C# 7 is supported in Xamarin Workbooks 1.2 (or newer).
> Please update to version 1.2 if you experience issues with this Workbook (you may need to switch to the Alpha or Beta channel).

# What's new in C# 7

C# 7 adds a number of new features to the C# language:

* `out` variables

  * You can declare `out` values inline as arguments to the method where they are used.

* Tuples

  * You can create lightweight, unnamed types that contain multiple public fields. Compilers and IDE tools understand the semantics of these types.

* Pattern Matching

  * You can create branching logic based on arbitrary types and values of the members of those types.

* `ref` locals and returns

  * Method arguments and local variables can be references to other storage.

* Local Functions

  * You can nest functions inside other functions to limit their scope and visibility.

* More expression-bodied members

  * The list of members that can be authored using expressions has grown.

* `throw` Expressions

  * You can throw exceptions in code constructs that previously were not allowed because `throw` was a statement.

* Generalized async return types

  * Methods declared with the `async` modifier can return other types in addition to `Task` and `Task<T>`.

* Numeric literal syntax improvements

  * New tokens improve readability for numeric constants.

The remainder of this topic discusses each of the features. For each feature, you'll learn the reasoning behind it. You'll learn the syntax. You'll see some sample scenarios where using the new feature will make you more productive as a developer.

## `out` variables

The existing syntax that supports `out` parameters has been improved in this version.

Previously, you would need to separate the declaration of the out variable and its initialization into two different statements:

```csharp
var input = "8675309";

int numericResult;
if (int.TryParse(input, out numericResult))
    Console.WriteLine(numericResult);
else
    Console.WriteLine("Could not parse input");
```

You can now declare `out` variables in the argument list of a method call, rather than writing a separate declaration statement:

```csharp
if (int.TryParse(input, out int result))
    Console.WriteLine(result);
else
    Console.WriteLine("Could not parse input");
```

You may want to specify the type of the `out` variable for clarity, as shown above. However, the language does support using an implicitly typed local variable:

```csharp
if (int.TryParse(input, out var answer))
    Console.WriteLine(answer);
else
    Console.WriteLine("Could not parse input");
```

* The code is easier to read.

  * You declare the out variable where you use it, not on another line above.

* No need to assign an initial value.

  * By declaring the `out` variable where it is used in a method call, you can't accidentally use it before it is assigned.

The most common use for this feature will be the `Try` pattern. In this pattern, a method returns a `bool` indicating success or failure and an`out` variable that provides the result if the method succeeds.

## Tuples

C# provides a rich syntax for classes and structs that is used to explain your design intent. But sometimes that rich syntax requires extra work with minimal benefit. You may often write methods that need a simple structure containing more than one data element. To support these scenarios *tuples* were added to C#. Tuples are lightweight data structures that contain multiple fields to represent the data members. The fields are not validated, and you cannot define your own methods

> ℹ️  Tuples were available before C# 7 as an API, but had many limitations. Most importantly, the members of these tuples were named `Item1`, `Item2` and so on. The language support enables semantic names for the fields of a Tuple.

You can create a tuple by assigning each member to a value:

```csharp
var letters = ("a", "b");
```

That assignment creates a tuple whose members are `Item1` and `Item2`, following the existing System.Tuple syntax. You can modify that assignment to create a tuple that provides semantic names to each of the members of the tuple:

```csharp
(string Alpha, string Beta) namedLetters = ("a", "b");
```

> ℹ️  The new tuples features require the `System.ValueTuple` type. For Visual Studio 15 Preview 5 and earlier preview releases, you must add the NuGet package "System.ValueTuple", available in the pre-release stream.

The `namedLetters` tuple contains fields referred to as `Alpha` and `Beta`. In a tuple assignment, you can also specify the names of the fields on the right-hand side of the assignment:

```csharp
var alphabetStart = (Alpha: "a", Beta: "b");
```

The language allows you to specify names for the fields on both the left and right-hand side of the assignment:

```csharp
(string First, string Second) firstLetters = (Alpha: "a", Beta: "b");
```

The line above generates a warning, `CS8123`, telling you that the names on the right side of the assignment, `Alpha` and `Beta` are ignored because they conflict with the names on the left side, `First` and `Second`.

The examples above show the basic syntax to declare tuples. Tuples are most useful as return types for `private` and `internal` methods. Tuples provide a simple syntax for those methods to return multiple discrete values: You save the work of authoring a `class` or a `struct` that defines the type returned. There is no need for creating a new type.

Creating a tuple is more efficient and more productive. It is a simpler, lightweight syntax to define a data structure that carries more than one value. The example method below returns the minimum and maximum values found in a sequence of integers:

```csharp
private static (int Max, int Min) Range(IEnumerable<int> numbers)
{
    int min = int.MaxValue;
    int max = int.MinValue;
    foreach(var n in numbers)
    {
        min = (n < min) ? n : min;
        max = (n > max) ? n : max;
    }
    return (max, min);
}
```

Using tuples in this way offers several advantages:

* You save the work of authoring a `class` or a `struct` that defines the type returned.

* You do not need to create new type.

* The language enhancements removes the need to call the `System.Tuple.Create<T>()` methods.

The declaration for the method provides the names for the fields of the tuple that is returned. When you call the method, the return value is a tuple whose fields are `Max` and `Min`:

```csharp
int [] numbers = { 97, 243, 254, 41, 132, 26, 167, 19, 201, 252, 119, 68, 17, 66, 131 };

var range = Range(numbers);
```

There may be times when you want to unpackage the members of a tuple that were returned from a method.  You can do that by declaring separate variables for each of the values in the tuple. This is called *deconstructing* the tuple:

```csharp
(int max, int min) = Range(numbers);
```

You can also provide a similar deconstruction for any type in .NET. This is done by writing a `Deconstruct` method as a member of the class. That `Deconstruct` method provides a set of `out` arguments for each of the properties you want to extract. Consider this `Point` class that provides a deconstructor method that extracts the `X` and `Y` coordinates:

```csharp
public class Point
{
    public Point(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public void Deconstruct(out double x, out double y)
    {
        x = this.X;
        y = this.Y;
    }
}
```

You can extract the individual fields by assigning a tuple to a `Point`:

```csharp
var p = new Point(3.14, 2.71);
(double X, double Y) = p;
```

You are not bound by the names defined in the `Deconstruct` method. You can rename the extract variables as part of the assignment:

```csharp
(double horizontalDistance, double verticalDistance) = p;
```

## Pattern matching

*Pattern matching* is a feature that allows you to implement method dispatch on properties other than the type of an object. You're probably already familiar with method dispatch based on the type of an object. In Object Oriented programming, virtual and override methods provide language syntax to implement method dispatching based on an object's type. Base and Derived classes provide different implementations. Pattern matching expressions extend this concept so that you can easily implement similar dispatch patterns for types and data elements that are not related through an inheritance hierarchy.

Pattern matching supports `is` expressions and `switch` expressions. Each enables inspecting an object and its properties to determine if that object satisfies the sought pattern. You use the `when` keyword to specify additional rules to the pattern.

### `is` expressions

The `is` pattern expressions extend the familiar `is` operator to query a object beyond its type.

Let's start with a simple scenario. We'll add capabilities to this scenario that demonstrate how pattern matching expressions make algorithms that work with unrelated types easy. We'll start with a method that computes the sum of a number of die rolls:

```csharp
public static int DiceSum(IEnumerable<int> values) => values.Sum()
```

You might quickly find that you need to find the sum of die rolls where some of the rolls are made with more than one die. Part of the input sequence may be multiple results instead of a single number:

```csharp
public static int DiceSum2(IEnumerable<object> values)
{
    var sum = 0;
    foreach(var item in values)
    {
        if (item is int val)
            sum += val;
        else if (item is IEnumerable<object> subList)
            sum += DiceSum2(subList);
    }
    return sum;
}
```

The `is` pattern expression works quite well in this scenario. As part of checking the type, you write a variable initialization. This creates a new variable of the validated runtime type.

As you keep extending these scenarios, you may find that you build more `if` and `else if` statements. Once that becomes unwieldy, you'll likely want to switch to `switch` pattern expressions.

### `switch` expressions

The `switch` pattern expression has a familiar syntax, based on the `switch` statement already part of the C# language. Let's translate the existing code to use a `switch` expression before adding new cases:

```csharp
public static int DiceSum3(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case int val:
                sum += val;
                break;
            case IEnumerable<object> subList:
                sum += DiceSum3(subList);
                break;
        }
    }
    return sum;
}
```

The `switch` expressions have a slightly different syntax than the `is` expressions, where you declare the type and variable at the beginning of the `case` expression.

The `switch` expressions also support constants. This can save time by factoring out simple cases:

```csharp
public static int DiceSum4(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case 0:
                break;
            case int val:
                sum += val;
                break;
            case IEnumerable<object> subList when subList.Any():
                sum += DiceSum4(subList);
                break;
            case IEnumerable<object> subList:
                break;
            case null:
                break;
            default:
                throw new InvalidOperationException("unknown item type");
        }
    }
    return sum;
}
```

The code above adds cases for `0` as a special case of `int`, and `null` as a special case when there is no input. This demonstrates one important new feature in switch pattern expressions: the order of the `case` expressions now matters. The `0` case must appear before the general `int` case. Otherwise, the first pattern to match would be the `int` case, even when the value is `0`.

This same behavior enables the special case for an empty input sequence. You can see that the case for an `IEnumerable` item that has elements must appear before the general `IEnumerable` case.

This version has also added a `default` case. The `default` case is always evaluated last, regardless of the order it appears in the source. For that reason, convention is to put the `default` case last.

Finally, let's add one last `case` for a new style of die. Some games use percentile dice to represent larger ranges of numbers.

> ℹ️  Two 10-sided percentile dice can represent every number from 0 through 99. One die has sides labelled `00`, `10`, `20`, ... `90`. The other die has sides labeled `0`, `1`, `2`, ... `9`. Add the two die values together and you can get every number from 0 through 99.

To add this kind of die to your collection, first define a type to represent the percentile die:

```csharp
public struct PercentileDie
{
    public int Value { get; }
    public int Multiplier { get; }

    public PercentileDie(int multiplier, int value)
    {
        this.Value = value;
        this.Multiplier = multiplier;
    }
}
```

Then, add a `case` expression for the new type:

```csharp
public static int DiceSum5(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case 0:
                break;
            case int val:
                sum += val;
                break;
            case PercentileDie die:
                sum += die.Multiplier * die.Value;
                break;
            case IEnumerable<object> subList when subList.Any():
                sum += DiceSum5(subList);
                break;
            case IEnumerable<object> subList:
                break;
            case null:
                break;
            default:
                throw new InvalidOperationException("unknown item type");
        }
    }
    return sum;
}
```

The new syntax for pattern matching expressions makes it easier to create dispatch algorithms based on an object's type, or other properties, using a clear and concise syntax. Pattern matching expressions enable these constructs on data types that are unrelated by inheritance.

## Local functions

Many designs for classes include methods that are called from only one location. These additional private methods keep each method small and focused. However, they can make it harder to understand a class when reading it the first time. These methods must be understood outside of the context of the single calling location.

For those designs, *local functions* enable you to declare methods inside the context of another method. This makes it easier for readers of the class to see that the local method is only called from the context in which is it declared.

There are two very common use cases for local functions: public iterator methods and public async methods. Both types of methods generate code that reports errors later than programmers might expect. In the case of iterator methods, any exceptions are observed only when calling code that enumerates the returned sequence. In the case of async methods, any exceptions are only observed when the returned `Task` is awaited.

Let's start with an iterator method:

```csharp
public static IEnumerable<char> AlphabetSubset(char start, char end)
{
    if ((start < 'a') || (start > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if ((end < 'a') || (end > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    for (var c = start; c < end; c++)
        yield return c;
}
```

Examine the code below that calls the iterator method incorrectly:

```csharp
var resultSet = AlphabetSubset('f', 'a');
Console.WriteLine("iterator created");
foreach (var thing in resultSet)
    Console.Write($"{thing}, ");
```

The exception is thrown when `resultSet` is iterated, not when `resultSet` is created. In this contained example, most developers could quickly diagnose the problem. However, in larger codebases, the code that creates an iterator often isn't as close to the code that enumerates the result. You can refactor the code so that the public method validates all arguments, and a private method generates the enumeration:

```csharp
public static IEnumerable<char> AlphabetSubset2(char start, char end)
{
    if ((start < 'a') || (start > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if ((end < 'a') || (end > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    return alphabetSubsetImplementation(start, end);
}

private static IEnumerable<char> alphabetSubsetImplementation(char start, char end)
{ 
    for (var c = start; c < end; c++)
        yield return c;
}
```

This refactored version will throw exceptions immediately because the public method is not an iterator method; only the private method uses the `yield return` syntax. However, there are potential problems with this refactoring. The private method should only be called from the public interface method, because otherwise all argument validation is skipped. Readers of the class must discover this fact by reading the entire class and searching for any other references to the `alphabetSubsetImplementation` method.

You can make that design intent more clear by declaring the `alphabetSubsetImplementation` as a local function inside the public API method:

```csharp
public static IEnumerable<char> AlphabetSubset3(char start, char end)
{
    if ((start < 'a') || (start > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if ((end < 'a') || (end > 'z'))
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");

    return alphabetSubsetImplementation();

    IEnumerable<char> alphabetSubsetImplementation()
    {
        for (var c = start; c < end; c++)
            yield return c;
    }
}
```

The version above makes it clear that the local method is referenced only in the context of the outer method. The rules for local functions also ensure that a developer can't accidentally call the local function from another location in the class and bypass the argument validation.

The same technique can be employed with `async` methods to ensure that exceptions arising from argument validation are thrown before the asynchronous work begins:

```csharp
public Task<string> PerformLongRunningWork(string address, int index, string name)
{
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException(message: "An address is required", paramName: nameof(address));
    if (index < 0)
        throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");
    if (string.IsNullOrWhiteSpace(name))
        throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));

    return longRunningWorkImplementation();

    async Task<string> longRunningWorkImplementation()
    {
        var interimResult = await FirstWork(address);
        var secondResult = await SecondStep(index, name);
        return $"The results are {interimResult} and {secondResult}. Enjoy.";

        Task<string> FirstWork(string x) => Task.FromResult (x);
        Task<string> SecondStep(int i, string x) => Task.FromResult ($"{x}: {i}");
    }
}
```

> ℹ️  Some of the designs that are supported by local functions could also be accomplished using *lambda expressions*.

## More expression-bodied members

C# 6 introduced expression-bodied members for member functions, and read-only properties. C# 7 expands the allowed members that can be implemented as expressions. In C# 7, you can implement *constructors*, *finalizers*, and `get` and `set` accessors on *properties* and *indexers*. The following code shows examples of each:

```csharp
class ExpressionMembersExample
{
    // Expression-bodied constructor
    public ExpressionMembersExample(string label) => this.Label = label;

    // Expression-bodied finalizer
    ~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

    private string label;

    // Expression-bodied get / set accessors.
    public string Label
    {
        get => label;
        set => this.label = value ?? "Default label";
    }
}
```

> ℹ️  This example does not need a finalizer, but it is shown to demonstrate the syntax. You should not implement a finalizer in your class unless it is necessary to  release unmanaged resources. You should also consider using the `System.Runtime.InteropServices.SafeHandle` class instead of managing unmanaged resources directly.

These new locations for expression-bodied members represent an important milestone for the C# language: These features were implemented by community members working on the open-source [Roslyn](https://github.com/dotnet/Roslyn) project.

## Throw expressions

In C#, `throw` has always been a statement. Because `throw` is a statement, not an expression, there were C# constructs where you could not use it. These included conditional expressions, null coalescing expressions, and some lambda expressions. The addition of expression-bodied members adds more locations where `throw` expressions would be useful. So that you can write any of these constructs, C# 7 introduces *throw expressions*.

The syntax is the same as you've always used for `throw` statements. The only difference is that now you can place them in new locations, such as in a conditional expression:

```csharp
class ExpressionMembersExample
{
    private string name;

    public string Name
    {
        get => name;
        set => name = value ?? 
            throw new ArgumentNullException(paramName: nameof(value), message: "New name must not be null");
    }
}
```

This features enables using throw expressions in initialization expressions:

```csharp
class ConfigResource { }
static ConfigResource LoadConfigResourceOrDefault () => null;

private ConfigResource loadedConfig = LoadConfigResourceOrDefault() ?? 
   throw new InvalidOperationException("Could not load config");
```

Previously, those initializations would need to be in a constructor, with the throw statements in the body of the constructor:

```csharp
class ApplicationOptions
{
    public ApplicationOptions()
    {
        var loadedConfig = LoadConfigResourceOrDefault();
        if (loadedConfig == null)
            throw new InvalidOperationException("Could not load config");
    }
}
```

> ℹ️  Both of the preceding constructs will cause exceptions to be thrown during the construction of an object. Those are often difficult to recover from. For that reason, designs that throw exceptions during construction are discouraged.

## Numeric literal syntax improvements

Misreading numeric constants can make it harder to understand code when reading it for the first time. This often occurs when those numbers are used as bit masks or other symbolic rather than numeric values. C# 7 includes two new features to make it easier to write numbers in the most readable fashion for the intended use: *binary literals*, and *digit separators*.

For those times when you are creating bit masks, or whenever a binary representation of a number makes the most readable code, write that number in binary:

```csharp
public const int One =  0b0001;
public const int Two =  0b0010;
public const int Four = 0b0100;
public const int Eight = 0b1000;
```

The `0b` at the beginning of the constant indicates that the number is written as a binary number.

Binary numbers can get very long, so it's often easier to see the bit patterns by introducing the `_` as a digit separator:

```csharp
public const int Sixteen =   0b0001_0000;
public const int ThirtyTwo = 0b0010_0000;
public const int SixtyFour = 0b0100_0000;
public const int OneHundredTwentyEight = 0b1000_0000;
```

The digit separator can appear anywhere in the constant. For base 10 numbers, it would be common to use it as a thousands separator:

```csharp
public const long BillionsAndBillions = 100_000_000_000;
```

The digit separator can be used with `decimal`, `float` and `double` types as well:

```csharp
public const double AvogadroConstant = 6.022_140_857_747_474e23;
public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;
```

Taken together, you can declare numeric constants with much more readability.

## Ref locals and returns

This feature enables algorithms that use and return references to variables defined elsewhere. One example is working with large matrices, and finding a single location with certain characteristics. One method would return the two indices for a single location in the matrix:

```csharp
public static (int i, int j) Find(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return (i, j);
    return (-1, -1); // Not found
}
```

There are many issues with this code. First of all, it's a public method that's returning a tuple. The language supports this, but user defined types (either classes or structs) are preferred for public APIs.

Second, this method is returning the indices to the item in the matrix. That leads callers to write code that uses those indices to dereference the matrix and modify a single element:

```csharp
var matrix = new int[,] {
    { 5, 9, 11, 4},
    { 3, 10, 18, 9},
    { 1, 19, 42, 2},
    { 0, 3, 4, 31},
};

var indices = Find(matrix, (val) => val == 42);
Console.WriteLine(indices);
matrix[indices.i, indices.j] = 24;
```

You'd rather write a method that returns a *reference* to the element of the matrix that you want to change. You could only accomplish this by using unsafe code and returning a pointer to an `int` in previous versions.

Let's walk through a series of changes to demonstrate the ref local feature and show how to create a method that returns a reference to internal storage. Along the way, you'll learn the rules of the ref return and ref local feature that protects you from accidentally misusing it.

Start by modifying the `Find` method declaration so that it returns a `ref int` instead of a tuple. Then, modify the return statement so it returns the value stored in the matrix instead of the two indices:

```csharp
// Note that this won't compile.
// Method declaration indicates ref return,
// but return statement specifies a value return.
//
// public static ref int Find2(int[,] matrix, Func<int, bool> predicate)
// {
//     for (int i = 0; i < matrix.GetLength(0); i++)
//         for (int j = 0; j < matrix.GetLength(1); j++)
//             if (predicate(matrix[i, j]))
//                 return matrix[i, j];
//     throw new InvalidOperationException("Not found");
// }
```

When you declare that a method returns a `ref` variable, you must also add the `ref` keyword to each return statement. That indicates return by reference, and helps developers reading the code later remember that the method returns by reference:

```csharp
public static ref int Find3(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return ref matrix[i, j];
    throw new InvalidOperationException("Not found");
}
```

Now that the method returns a reference to the integer value in the matrix, you need to modify where it's called.  The `var` declaration means that `valItem` is now an `int` rather than a tuple:

```csharp
var valItem = Find3(matrix, (val) => val == 42);
Console.WriteLine(valItem);
valItem = 24;
Console.WriteLine(matrix[4, 2]);
```

The second `WriteLine` statement in the example above prints out the value `42`, not `24`. The variable `valItem` is an `int`, not a `ref int`. The `var` keyword enables the compiler to specify the type, but will not implicitly add the `ref` modifier. Instead, the value referred to by the `ref return` is *copied* to the variable on the left-hand side of the assignment. The variable is not a `ref` local.

In order to get the result you want, you need to add the `ref` modifier to the local variable declaration to make the variable a reference when the return value is a reference:

```csharp
ref var item = ref Find3(matrix, (val) => val == 42);
Console.WriteLine(item);
item = 24;
Console.WriteLine(matrix[4, 2]);
```

Now, the second `WriteLine` statement in the example above will print out the value `24`, indicating that the storage in the matrix has been modified. The local variable has been declared with the `ref` modifier, and it will take a `ref` return. You must initialize a `ref` variable when it is declared, you cannot split the declaration and the initialization.

The C# language has two other rules that protect you from misusing the `ref` locals and returns:

* You cannot assign a value to a `ref` variable.

  * That disallows statements like `ref int i = sequence.Count();`

* You cannot return a `ref` to a variable whose lifetime does not extend beyond the execution of the method.

  * That means you cannot return a reference to a local variable, or similar scope.

These rules ensure that you cannot accidentally mix value variables and reference variables. They also ensure that you cannot have a reference variable refer to storage that is a candidate for garbage collection.

The addition of ref locals and ref returns enable algorithms that are more efficient by avoiding copying values, or performing dereferencing operations multiple times.


================================================
FILE: csharp/csharp7/meta.json
================================================
{
  "order":{
    "csharp7.workbook":"What's new in C# 7"
  }
}


================================================
FILE: csharp/linq/101-linq-examples.workbook/101_Linq_Examples.csx
================================================
#r "System.Xml.Linq"
#r "System.Data"
#r "System.Data.DataSetExtensions"

using System.Xml.Linq;
using System.Data;


public class Product
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public string Category { get; set; }
    public decimal UnitPrice { get; set; }
    public int UnitsInStock { get; set; }
}

public class Order
{
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal Total { get; set; }
}

public class Customer
{
    public string CustomerID { get; set; }
    public string CompanyName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string Region { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    public string Phone { get; set; }
    public string Fax { get; set; }
    public Order[] Orders { get; set; }
}

// Data
var productList = 
    new List<Product> {
    new Product { ProductID = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 39 },
    new Product { ProductID = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000M, UnitsInStock = 17 },
    new Product { ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000M, UnitsInStock = 13 },
    new Product { ProductID = 4, ProductName = "Chef Anton's Cajun Seasoning", Category = "Condiments", UnitPrice = 22.0000M, UnitsInStock = 53 },
    new Product { ProductID = 5, ProductName = "Chef Anton's Gumbo Mix", Category = "Condiments", UnitPrice = 21.3500M, UnitsInStock = 0 },
    new Product { ProductID = 6, ProductName = "Grandma's Boysenberry Spread", Category = "Condiments", UnitPrice = 25.0000M, UnitsInStock = 120 },
    new Product { ProductID = 7, ProductName = "Uncle Bob's Organic Dried Pears", Category = "Produce", UnitPrice = 30.0000M, UnitsInStock = 15 },
    new Product { ProductID = 8, ProductName = "Northwoods Cranberry Sauce", Category = "Condiments", UnitPrice = 40.0000M, UnitsInStock = 6 },
    new Product { ProductID = 9, ProductName = "Mishi Kobe Niku", Category = "Meat/Poultry", UnitPrice = 97.0000M, UnitsInStock = 29 },
    new Product { ProductID = 10, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 31 },
    new Product { ProductID = 11, ProductName = "Queso Cabrales", Category = "Dairy Products", UnitPrice = 21.0000M, UnitsInStock = 22 },
    new Product { ProductID = 12, ProductName = "Queso Manchego La Pastora", Category = "Dairy Products", UnitPrice = 38.0000M, UnitsInStock = 86 },
    new Product { ProductID = 13, ProductName = "Konbu", Category = "Seafood", UnitPrice = 6.0000M, UnitsInStock = 24 },
    new Product { ProductID = 14, ProductName = "Tofu", Category = "Produce", UnitPrice = 23.2500M, UnitsInStock = 35 },
    new Product { ProductID = 15, ProductName = "Genen Shouyu", Category = "Condiments", UnitPrice = 15.5000M, UnitsInStock = 39 },
    new Product { ProductID = 16, ProductName = "Pavlova", Category = "Confections", UnitPrice = 17.4500M, UnitsInStock = 29 },
    new Product { ProductID = 17, ProductName = "Alice Mutton", Category = "Meat/Poultry", UnitPrice = 39.0000M, UnitsInStock = 0 },
    new Product { ProductID = 18, ProductName = "Carnarvon Tigers", Category = "Seafood", UnitPrice = 62.5000M, UnitsInStock = 42 },
    new Product { ProductID = 19, ProductName = "Teatime Chocolate Biscuits", Category = "Confections", UnitPrice = 9.2000M, UnitsInStock = 25 },
    new Product { ProductID = 20, ProductName = "Sir Rodney's Marmalade", Category = "Confections", UnitPrice = 81.0000M, UnitsInStock = 40 },
    new Product { ProductID = 21, ProductName = "Sir Rodney's Scones", Category = "Confections", UnitPrice = 10.0000M, UnitsInStock = 3 },
    new Product { ProductID = 22, ProductName = "Gustaf's Knäckebröd", Category = "Grains/Cereals", UnitPrice = 21.0000M, UnitsInStock = 104 },
    new Product { ProductID = 23, ProductName = "Tunnbröd", Category = "Grains/Cereals", UnitPrice = 9.0000M, UnitsInStock = 61 },
    new Product { ProductID = 24, ProductName = "Guaraná Fantástica", Category = "Beverages", UnitPrice = 4.5000M, UnitsInStock = 20 },
    new Product { ProductID = 25, ProductName = "NuNuCa Nuß-Nougat-Creme", Category = "Confections", UnitPrice = 14.0000M, UnitsInStock = 76 },
    new Product { ProductID = 26, ProductName = "Gumbär Gummibärchen", Category = "Confections", UnitPrice = 31.2300M, UnitsInStock = 15 },
    new Product { ProductID = 27, ProductName = "Schoggi Schokolade", Category = "Confections", UnitPrice = 43.9000M, UnitsInStock = 49 },
    new Product { ProductID = 28, ProductName = "Rössle Sauerkraut", Category = "Produce", UnitPrice = 45.6000M, UnitsInStock = 26 },
    new Product { ProductID = 29, ProductName = "Thüringer Rostbratwurst", Category = "Meat/Poultry", UnitPrice = 123.7900M, UnitsInStock = 0 },
    new Product { ProductID = 30, ProductName = "Nord-Ost Matjeshering", Category = "Seafood", UnitPrice = 25.8900M, UnitsInStock = 10 },
    new Product { ProductID = 31, ProductName = "Gorgonzola Telino", Category = "Dairy Products", UnitPrice = 12.5000M, UnitsInStock = 0 },
    new Product { ProductID = 32, ProductName = "Mascarpone Fabioli", Category = "Dairy Products", UnitPrice = 32.0000M, UnitsInStock = 9 },
    new Product { ProductID = 33, ProductName = "Geitost", Category = "Dairy Products", UnitPrice = 2.5000M, UnitsInStock = 112 },
    new Product { ProductID = 34, ProductName = "Sasquatch Ale", Category = "Beverages", UnitPrice = 14.0000M, UnitsInStock = 111 },
    new Product { ProductID = 35, ProductName = "Steeleye Stout", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 20 },
    new Product { ProductID = 36, ProductName = "Inlagd Sill", Category = "Seafood", UnitPrice = 19.0000M, UnitsInStock = 112 },
    new Product { ProductID = 37, ProductName = "Gravad lax", Category = "Seafood", UnitPrice = 26.0000M, UnitsInStock = 11 },
    new Product { ProductID = 38, ProductName = "Côte de Blaye", Category = "Beverages", UnitPrice = 263.5000M, UnitsInStock = 17 },
    new Product { ProductID = 39, ProductName = "Chartreuse verte", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 69 },
    new Product { ProductID = 40, ProductName = "Boston Crab Meat", Category = "Seafood", UnitPrice = 18.4000M, UnitsInStock = 123 },
    new Product { ProductID = 41, ProductName = "Jack's New England Clam Chowder", Category = "Seafood", UnitPrice = 9.6500M, UnitsInStock = 85 },
    new Product { ProductID = 42, ProductName = "Singaporean Hokkien Fried Mee", Category = "Grains/Cereals", UnitPrice = 14.0000M, UnitsInStock = 26 },
    new Product { ProductID = 43, ProductName = "Ipoh Coffee", Category = "Beverages", UnitPrice = 46.0000M, UnitsInStock = 17 },
    new Product { ProductID = 44, ProductName = "Gula Malacca", Category = "Condiments", UnitPrice = 19.4500M, UnitsInStock = 27 },
    new Product { ProductID = 45, ProductName = "Rogede sild", Category = "Seafood", UnitPrice = 9.5000M, UnitsInStock = 5 },
    new Product { ProductID = 46, ProductName = "Spegesild", Category = "Seafood", UnitPrice = 12.0000M, UnitsInStock = 95 },
    new Product { ProductID = 47, ProductName = "Zaanse koeken", Category = "Confections", UnitPrice = 9.5000M, UnitsInStock = 36 },
    new Product { ProductID = 48, ProductName = "Chocolade", Category = "Confections", UnitPrice = 12.7500M, UnitsInStock = 15 },
    new Product { ProductID = 49, ProductName = "Maxilaku", Category = "Confections", UnitPrice = 20.0000M, UnitsInStock = 10 },
    new Product { ProductID = 50, ProductName = "Valkoinen suklaa", Category = "Confections", UnitPrice = 16.2500M, UnitsInStock = 65 },
    new Product { ProductID = 51, ProductName = "Manjimup Dried Apples", Category = "Produce", UnitPrice = 53.0000M, UnitsInStock = 20 },
    new Product { ProductID = 52, ProductName = "Filo Mix", Category = "Grains/Cereals", UnitPrice = 7.0000M, UnitsInStock = 38 },
    new Product { ProductID = 53, ProductName = "Perth Pasties", Category = "Meat/Poultry", UnitPrice = 32.8000M, UnitsInStock = 0 },
    new Product { ProductID = 54, ProductName = "Tourtière", Category = "Meat/Poultry", UnitPrice = 7.4500M, UnitsInStock = 21 },
    new Product { ProductID = 55, ProductName = "Pâté chinois", Category = "Meat/Poultry", UnitPrice = 24.0000M, UnitsInStock = 115 },
    new Product { ProductID = 56, ProductName = "Gnocchi di nonna Alice", Category = "Grains/Cereals", UnitPrice = 38.0000M, UnitsInStock = 21 },
    new Product { ProductID = 57, ProductName = "Ravioli Angelo", Category = "Grains/Cereals", UnitPrice = 19.5000M, UnitsInStock = 36 },
    new Product { ProductID = 58, ProductName = "Escargots de Bourgogne", Category = "Seafood", UnitPrice = 13.2500M, UnitsInStock = 62 },
    new Product { ProductID = 59, ProductName = "Raclette Courdavault", Category = "Dairy Products", UnitPrice = 55.0000M, UnitsInStock = 79 },
    new Product { ProductID = 60, ProductName = "Camembert Pierrot", Category = "Dairy Products", UnitPrice = 34.0000M, UnitsInStock = 19 },
    new Product { ProductID = 61, ProductName = "Sirop d'érable", Category = "Condiments", UnitPrice = 28.5000M, UnitsInStock = 113 },
    new Product { ProductID = 62, ProductName = "Tarte au sucre", Category = "Confections", UnitPrice = 49.3000M, UnitsInStock = 17 },
    new Product { ProductID = 63, ProductName = "Vegie-spread", Category = "Condiments", UnitPrice = 43.9000M, UnitsInStock = 24 },
    new Product { ProductID = 64, ProductName = "Wimmers gute Semmelknödel", Category = "Grains/Cereals", UnitPrice = 33.2500M, UnitsInStock = 22 },
    new Product { ProductID = 65, ProductName = "Louisiana Fiery Hot Pepper Sauce", Category = "Condiments", UnitPrice = 21.0500M, UnitsInStock = 76 },
    new Product { ProductID = 66, ProductName = "Louisiana Hot Spiced Okra", Category = "Condiments", UnitPrice = 17.0000M, UnitsInStock = 4 },
    new Product { ProductID = 67, ProductName = "Laughing Lumberjack Lager", Category = "Beverages", UnitPrice = 14.0000M, UnitsInStock = 52 },
    new Product { ProductID = 68, ProductName = "Scottish Longbreads", Category = "Confections", UnitPrice = 12.5000M, UnitsInStock = 6 },
    new Product { ProductID = 69, ProductName = "Gudbrandsdalsost", Category = "Dairy Products", UnitPrice = 36.0000M, UnitsInStock = 26 },
    new Product { ProductID = 70, ProductName = "Outback Lager", Category = "Beverages", UnitPrice = 15.0000M, UnitsInStock = 15 },
    new Product { ProductID = 71, ProductName = "Flotemysost", Category = "Dairy Products", UnitPrice = 21.5000M, UnitsInStock = 26 },
    new Product { ProductID = 72, ProductName = "Mozzarella di Giovanni", Category = "Dairy Products", UnitPrice = 34.8000M, UnitsInStock = 14 },
    new Product { ProductID = 73, ProductName = "Röd Kaviar", Category = "Seafood", UnitPrice = 15.0000M, UnitsInStock = 101 },
    new Product { ProductID = 74, ProductName = "Longlife Tofu", Category = "Produce", UnitPrice = 10.0000M, UnitsInStock = 4 },
    new Product { ProductID = 75, ProductName = "Rhönbräu Klosterbier", Category = "Beverages", UnitPrice = 7.7500M, UnitsInStock = 125 },
    new Product { ProductID = 76, ProductName = "Lakkalikööri", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 57 },
    new Product { ProductID = 77, ProductName = "Original Frankfurter grüne Soße", Category = "Condiments", UnitPrice = 13.0000M, UnitsInStock = 32 }
};

List<Product> GetProductList() => productList;

// Customer/Order data read into memory from XML file using XLinq:

var customerList = (
    from e in XDocument.Load("Customers.xml").
              Root.Elements("customer")
    select new Customer
    {
        CustomerID = (string)e.Element("id"),
        CompanyName = (string)e.Element("name"),
        Address = (string)e.Element("address"),
        City = (string)e.Element("city"),
        Region = (string)e.Element("region"),
        PostalCode = (string)e.Element("postalcode"),
        Country = (string)e.Element("country"),
        Phone = (string)e.Element("phone"),
        Fax = (string)e.Element("fax"),
        Orders = (
            from o in e.Elements("orders").Elements("order")
            select new Order
            {
                OrderID = (int)o.Element("id"),
                OrderDate = (DateTime)o.Element("orderdate"),
                Total = (decimal)o.Element("total")
            })
            .ToArray()
    })
    .ToList();

List<Customer> GetCustomerList() => customerList;

public class Supplier
{
    public string SupplierName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

var supplierList = new List<Supplier>(){
                    new Supplier {SupplierName = "Exotic Liquids", Address = "49 Gilbert St.", City = "London", Country = "UK"},
                    new Supplier {SupplierName = "New Orleans Cajun Delights", Address = "P.O. Box 78934", City = "New Orleans", Country = "USA"},
                    new Supplier {SupplierName = "Grandma Kelly's Homestead", Address = "707 Oxford Rd.", City = "Ann Arbor", Country = "USA"},
                    new Supplier {SupplierName = "Tokyo Traders", Address = "9-8 Sekimai Musashino-shi", City = "Tokyo", Country = "Japan"},
                    new Supplier {SupplierName = "Cooperativa de Quesos 'Las Cabras'", Address = "Calle del Rosal 4", City = "Oviedo", Country = "Spain"},
                    new Supplier {SupplierName = "Mayumi's", Address = "92 Setsuko Chuo-ku", City = "Osaka", Country = "Japan"},
                    new Supplier {SupplierName = "Pavlova, Ltd.", Address = "74 Rose St. Moonie Ponds", City = "Melbourne", Country = "Australia"},
                    new Supplier {SupplierName = "Specialty Biscuits, Ltd.", Address = "29 King's Way", City = "Manchester", Country = "UK"},
                    new Supplier {SupplierName = "PB Knäckebröd AB", Address = "Kaloadagatan 13", City = "Göteborg", Country = "Sweden"},
                    new Supplier {SupplierName = "Refrescos Americanas LTDA", Address = "Av. das Americanas 12.890", City = "Sao Paulo", Country = "Brazil"},
                    new Supplier {SupplierName = "Heli Süßwaren GmbH & Co. KG", Address = "Tiergartenstraße 5", City = "Berlin", Country = "Germany"},
                    new Supplier {SupplierName = "Plutzer Lebensmittelgroßmärkte AG", Address = "Bogenallee 51", City = "Frankfurt", Country = "Germany"},
                    new Supplier {SupplierName = "Nord-Ost-Fisch Handelsgesellschaft mbH", Address = "Frahmredder 112a", City = "Cuxhaven", Country = "Germany"},
                    new Supplier {SupplierName = "Formaggi Fortini s.r.l.", Address = "Viale Dante, 75", City = "Ravenna", Country = "Italy"},
                    new Supplier {SupplierName = "Norske Meierier", Address = "Hatlevegen 5", City = "Sandvika", Country = "Norway"},
                    new Supplier {SupplierName = "Bigfoot Breweries", Address = "3400 - 8th Avenue Suite 210", City = "Bend", Country = "USA"},
                    new Supplier {SupplierName = "Svensk Sjöföda AB", Address = "Brovallavägen 231", City = "Stockholm", Country = "Sweden"},
                    new Supplier {SupplierName = "Aux joyeux ecclésiastiques", Address = "203, Rue des Francs-Bourgeois", City = "Paris", Country = "France"},
                    new Supplier {SupplierName = "New England Seafood Cannery", Address = "Order Processing Dept. 2100 Paul Revere Blvd.", City = "Boston", Country = "USA"},
                    new Supplier {SupplierName = "Leka Trading", Address = "471 Serangoon Loop, Suite #402", City = "Singapore", Country = "Singapore"},
                    new Supplier {SupplierName = "Lyngbysild", Address = "Lyngbysild Fiskebakken 10", City = "Lyngby", Country = "Denmark"},
                    new Supplier {SupplierName = "Zaanse Snoepfabriek", Address = "Verkoop Rijnweg 22", City = "Zaandam", Country = "Netherlands"},
                    new Supplier {SupplierName = "Karkki Oy", Address = "Valtakatu 12", City = "Lappeenranta", Country = "Finland"},
                    new Supplier {SupplierName = "G'day, Mate", Address = "170 Prince Edward Parade Hunter's Hill", City = "Sydney", Country = "Australia"},
                    new Supplier {SupplierName = "Ma Maison", Address = "2960 Rue St. Laurent", City = "Montréal", Country = "Canada"},
                    new Supplier {SupplierName = "Pasta Buttini s.r.l.", Address = "Via dei Gelsomini, 153", City = "Salerno", Country = "Italy"},
                    new Supplier {SupplierName = "Escargots Nouveaux", Address = "22, rue H. Voiron", City = "Montceau", Country = "France"},
                    new Supplier {SupplierName = "Gai pâturage", Address = "Bat. B 3, rue des Alpes", City = "Annecy", Country = "France"},
                    new Supplier {SupplierName = "Forêts d'érables", Address = "148 rue Chasseur", City = "Ste-Hyacinthe", Country = "Canada"},
                };

List<Supplier> GetSupplierList() => supplierList;

#region Projection

var testDS = TestHelper.CreateTestDataset();

internal class TestHelper
    {

        internal static IEnumerable<string> ZipToStrings<T,U>(IEnumerable<T> xs, IEnumerable<U> ys, Func<T,U,string> fn){
            return xs.Zip(ys, fn);
        }

        internal static DataSet CreateTestDataset()
        {
            DataSet ds = new DataSet();

            // Customers Table
            ds.Tables.Add(CreateNumbersTable());
            ds.Tables.Add(CreateLowNumbersTable());
            ds.Tables.Add(CreateEmptyNumbersTable());
            ds.Tables.Add(CreateProductList());
            ds.Tables.Add(CreateDigitsTable());
            ds.Tables.Add(CreateWordsTable());
            ds.Tables.Add(CreateWords2Table());
            ds.Tables.Add(CreateWords3Table());
            ds.Tables.Add(CreateWords4Table());
            ds.Tables.Add(CreateAnagramsTable());
            ds.Tables.Add(CreateNumbersATable());
            ds.Tables.Add(CreateNumbersBTable());
            ds.Tables.Add(CreateFactorsOf300());
            ds.Tables.Add(CreateDoublesTable());
            ds.Tables.Add(CreateScoreRecordsTable());
            ds.Tables.Add(CreateAttemptedWithdrawalsTable());
            ds.Tables.Add(CreateEmployees1Table());
            ds.Tables.Add(CreateEmployees2Table());

            CreateCustomersAndOrdersTables(ds);

            ds.AcceptChanges();
            return ds;
        }


        private static DataTable CreateNumbersTable()
        {

            int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
            DataTable table = new DataTable("Numbers");
            table.Columns.Add("number", typeof(int));

            foreach (int n in numbers)
            {
                table.Rows.Add(new object[] { n });
            }

            return table;
        }

        private static DataTable CreateEmptyNumbersTable()
        {

            DataTable table = new DataTable("EmptyNumbers");
            table.Columns.Add("number", typeof(int));
            return table;
        }

        private static DataTable CreateDigitsTable()
        {

            string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
            DataTable table = new DataTable("Digits");
            table.Columns.Add("digit", typeof(string));

            foreach (string digit in digits)
            {
                table.Rows.Add(new object[] { digit });
            }
            return table;
        }

        private static DataTable CreateWordsTable()
        {
            string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
            DataTable table = new DataTable("Words");
            table.Columns.Add("word", typeof(string));

            foreach (string word in words)
            {
                table.Rows.Add(new object[] { word });
            }
            return table;
        }

        private static DataTable CreateWords2Table()
        {
            string[] words = { "believe", "relief", "receipt", "field" };
            DataTable table = new DataTable("Words2");
            table.Columns.Add("word", typeof(string));

            foreach (string word in words)
            {
                table.Rows.Add(new object[] { word });
            }
            return table;
        }

        private static DataTable CreateWords3Table()
        {
            string[] words = { "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" };
            DataTable table = new DataTable("Words3");
            table.Columns.Add("word", typeof(string));

            foreach (string word in words)
            {
                table.Rows.Add(new object[] { word });
            }
            return table;
        }

        private static DataTable CreateWords4Table()
        {
            string[] words = { "blueberry", "chimpanzee", "abacus", "banana", "apple", "cheese" };
            DataTable table = new DataTable("Words4");
            table.Columns.Add("word", typeof(string));

            foreach (string word in words)
            {
                table.Rows.Add(new object[] { word });
            }
            return table;
        }

        private static DataTable CreateAnagramsTable()
        {
            string[] anagrams = { "from   ", " salt", " earn ", "  last   ", " near ", " form  " };
            DataTable table = new DataTable("Anagrams");
            table.Columns.Add("anagram", typeof(string));

            foreach (string word in anagrams)
            {
                table.Rows.Add(new object[] { word });
            }
            return table;
        }

        private static DataTable CreateScoreRecordsTable()
        {
            var scoreRecords = new[] { new {Name = "Alice", Score = 50},
                                new {Name = "Bob"  , Score = 40},
                                new {Name = "Cathy", Score = 45}
                            };

            DataTable table = new DataTable("ScoreRecords");
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("Score", typeof(int));

            foreach (var r in scoreRecords)
            {
                table.Rows.Add(new object[] { r.Name, r.Score });
            }
            return table;
        }

        private static DataTable CreateAttemptedWithdrawalsTable()
        {
            int[] attemptedWithdrawals = { 20, 10, 40, 50, 10, 70, 30 };

            DataTable table = new DataTable("AttemptedWithdrawals");
            table.Columns.Add("withdrawal", typeof(int));

            foreach (var r in attemptedWithdrawals)
            {
                table.Rows.Add(new object[] { r });
            }
            return table;
        }

        private static DataTable CreateNumbersATable()
        {
            int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
            DataTable table = new DataTable("NumbersA");
            table.Columns.Add("number", typeof(int));

            foreach (int number in numbersA)
            {
                table.Rows.Add(new object[] { number });
            }
            return table;
        }

        private static DataTable CreateNumbersBTable()
        {
            int[] numbersB = { 1, 3, 5, 7, 8 };
            DataTable table = new DataTable("NumbersB");
            table.Columns.Add("number", typeof(int));

            foreach (int number in numbersB)
            {
                table.Rows.Add(new object[] { number });
            }
            return table;
        }

        private static DataTable CreateLowNumbersTable()
        {
            int[] lowNumbers = { 1, 11, 3, 19, 41, 65, 19 };
            DataTable table = new DataTable("LowNumbers");
            table.Columns.Add("number", typeof(int));

            foreach (int number in lowNumbers)
            {
                table.Rows.Add(new object[] { number });
            }
            return table;
        }

        private static DataTable CreateFactorsOf300()
        {
            int[] factorsOf300 = { 2, 2, 3, 5, 5 };

            DataTable table = new DataTable("FactorsOf300");
            table.Columns.Add("factor", typeof(int));

            foreach (int factor in factorsOf300)
            {
                table.Rows.Add(new object[] { factor });
            }
            return table;
        }

        private static DataTable CreateDoublesTable()
        {
            double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 };

            DataTable table = new DataTable("Doubles");
            table.Columns.Add("double", typeof(double));

            foreach (double d in doubles)
            {
                table.Rows.Add(new object[] { d });
            }
            return table;
        }

        private static DataTable CreateEmployees1Table()
        {

            DataTable table = new DataTable("Employees1");
            table.Columns.Add("id", typeof(int));
            table.Columns.Add("name", typeof(string));
            table.Columns.Add("worklevel", typeof(int));

            table.Rows.Add(new object[] { 1, "Jones", 5 });
            table.Rows.Add(new object[] { 2, "Smith", 5 });
            table.Rows.Add(new object[] { 2, "Smith", 5 });
            table.Rows.Add(new object[] { 3, "Smith", 6 });
            table.Rows.Add(new object[] { 4, "Arthur", 11 });
            table.Rows.Add(new object[] { 5, "Arthur", 12 });

            return table;
        }

        private static DataTable CreateEmployees2Table()
        {

            DataTable table = new DataTable("Employees2");
            table.Columns.Add("id", typeof(int));
            table.Columns.Add("lastname", typeof(string));
            table.Columns.Add("level", typeof(int));

            table.Rows.Add(new object[] { 1, "Jones", 10 });
            table.Rows.Add(new object[] { 2, "Jagger", 5 });
            table.Rows.Add(new object[] { 3, "Thomas", 6 });
            table.Rows.Add(new object[] { 4, "Collins", 11 });
            table.Rows.Add(new object[] { 4, "Collins", 12 });
            table.Rows.Add(new object[] { 5, "Arthur", 12 });

            return table;
        }

        private static void CreateCustomersAndOrdersTables(DataSet ds)
        {

            DataTable customers = new DataTable("Customers");
            customers.Columns.Add("CustomerID", typeof(string));
            customers.Columns.Add("CompanyName", typeof(string));
            customers.Columns.Add("Address", typeof(string));
            customers.Columns.Add("City", typeof(string));
            customers.Columns.Add("Region", typeof(string));
            customers.Columns.Add("PostalCode", typeof(string));
            customers.Columns.Add("Country", typeof(string));
            customers.Columns.Add("Phone", typeof(string));
            customers.Columns.Add("Fax", typeof(string));

            ds.Tables.Add(customers);

            DataTable orders = new DataTable("Orders");

            orders.Columns.Add("OrderID", typeof(int));
            orders.Columns.Add("CustomerID", typeof(string));
            orders.Columns.Add("OrderDate", typeof(DateTime));
            orders.Columns.Add("Total", typeof(decimal));

            ds.Tables.Add(orders);

            DataRelation co = new DataRelation("CustomersOrders", customers.Columns["CustomerID"], orders.Columns["CustomerID"], true);
            ds.Relations.Add(co);

            var customerList = (
                from e in XDocument.Load("customers.xml").
                          Root.Elements("customer")
                select new Customer
                {
                    CustomerID = (string)e.Element("id"),
                    CompanyName = (string)e.Element("name"),
                    Address = (string)e.Element("address"),
                    City = (string)e.Element("city"),
                    Region = (string)e.Element("region"),
                    PostalCode = (string)e.Element("postalcode"),
                    Country = (string)e.Element("country"),
                    Phone = (string)e.Element("phone"),
                    Fax = (string)e.Element("fax"),
                    Orders = (
                        from o in e.Elements("orders").Elements("order")
                        select new Order
                        {
                            OrderID = (int)o.Element("id"),
                            OrderDate = (DateTime)o.Element("orderdate"),
                            Total = (decimal)o.Element("total")
                        })
                        .ToArray()
                }
                ).ToList();

            foreach (Customer cust in customerList)
            {
                customers.Rows.Add(new object[] {cust.CustomerID, cust.CompanyName, cust.Address, cust.City, cust.Region,
                                                cust.PostalCode, cust.Country, cust.Phone, cust.Fax});
                foreach (Order order in cust.Orders)
                {
                    orders.Rows.Add(new object[] { order.OrderID, cust.CustomerID, order.OrderDate, order.Total });
                }
            }
        }

        private static DataTable CreateProductList()
        {

            DataTable table = new DataTable("Products");
            table.Columns.Add("ProductID", typeof(int));
            table.Columns.Add("ProductName", typeof(string));
            table.Columns.Add("Category", typeof(string));
            table.Columns.Add("UnitPrice", typeof(decimal));
            table.Columns.Add("UnitsInStock", typeof(int));

            var productList = new[] {
              new { ProductID = 1, ProductName = "Chai", Category = "Beverages", 
                UnitPrice = 18.0000M, UnitsInStock = 39 },
              new { ProductID = 2, ProductName = "Chang", Category = "Beverages", 
                UnitPrice = 19.0000M, UnitsInStock = 17 },
              new { ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", 
                UnitPrice = 10.0000M, UnitsInStock = 13 },
              new { ProductID = 4, ProductName = "Chef Anton's Cajun Seasoning", Category = "Condiments", 
                UnitPrice = 22.0000M, UnitsInStock = 53 },
              new { ProductID = 5, ProductName = "Chef Anton's Gumbo Mix", Category = "Condiments", 
                UnitPrice = 21.3500M, UnitsInStock = 0 },
              new { ProductID = 6, ProductName = "Grandma's Boysenberry Spread", Category = "Condiments", 
                UnitPrice = 25.0000M, UnitsInStock = 120 },
              new { ProductID = 7, ProductName = "Uncle Bob's Organic Dried Pears", Category = "Produce", 
                UnitPrice = 30.0000M, UnitsInStock = 15 },
              new { ProductID = 8, ProductName = "Northwoods Cranberry Sauce", Category = "Condiments", 
                UnitPrice = 40.0000M, UnitsInStock = 6 },
              new { ProductID = 9, ProductName = "Mishi Kobe Niku", Category = "Meat/Poultry", 
                UnitPrice = 97.0000M, UnitsInStock = 29 },
              new { ProductID = 10, ProductName = "Ikura", Category = "Seafood", 
                UnitPrice = 31.0000M, UnitsInStock = 31 },
              new { ProductID = 11, ProductName = "Queso Cabrales", Category = "Dairy Products", 
                UnitPrice = 21.0000M, UnitsInStock = 22 },
              new { ProductID = 12, ProductName = "Queso Manchego La Pastora", Category = "Dairy Products", 
                UnitPrice = 38.0000M, UnitsInStock = 86 },
              new { ProductID = 13, ProductName = "Konbu", Category = "Seafood", 
                UnitPrice = 6.0000M, UnitsInStock = 24 },
              new { ProductID = 14, ProductName = "Tofu", Category = "Produce", 
                UnitPrice = 23.2500M, UnitsInStock = 35 },
              new { ProductID = 15, ProductName = "Genen Shouyu", Category = "Condiments", 
                UnitPrice = 15.5000M, UnitsInStock = 39 },
              new { ProductID = 16, ProductName = "Pavlova", Category = "Confections", 
                UnitPrice = 17.4500M, UnitsInStock = 29 },
              new { ProductID = 17, ProductName = "Alice Mutton", Category = "Meat/Poultry", 
                UnitPrice = 39.0000M, UnitsInStock = 0 },
              new { ProductID = 18, ProductName = "Carnarvon Tigers", Category = "Seafood", 
                UnitPrice = 62.5000M, UnitsInStock = 42 },
              new { ProductID = 19, ProductName = "Teatime Chocolate Biscuits", Category = "Confections", 
                UnitPrice = 9.2000M, UnitsInStock = 25 },
              new { ProductID = 20, ProductName = "Sir Rodney's Marmalade", Category = "Confections", 
                UnitPrice = 81.0000M, UnitsInStock = 40 },
              new { ProductID = 21, ProductName = "Sir Rodney's Scones", Category = "Confections", 
                UnitPrice = 10.0000M, UnitsInStock = 3 },
              new { ProductID = 22, ProductName = "Gustaf's Knäckebröd", Category = "Grains/Cereals", 
                UnitPrice = 21.0000M, UnitsInStock = 104 },
              new { ProductID = 23, ProductName = "Tunnbröd", Category = "Grains/Cereals", 
                UnitPrice = 9.0000M, UnitsInStock = 61 },
              new { ProductID = 24, ProductName = "Guaraná Fantástica", Category = "Beverages", 
                UnitPrice = 4.5000M, UnitsInStock = 20 },
              new { ProductID = 25, ProductName = "NuNuCa Nuß-Nougat-Creme", Category = "Confections", 
                UnitPrice = 14.0000M, UnitsInStock = 76 },
              new { ProductID = 26, ProductName = "Gumbär Gummibärchen", Category = "Confections", 
                UnitPrice = 31.2300M, UnitsInStock = 15 },
              new { ProductID = 27, ProductName = "Schoggi Schokolade", Category = "Confections", 
                UnitPrice = 43.9000M, UnitsInStock = 49 },
              new { ProductID = 28, ProductName = "Rössle Sauerkraut", Category = "Produce", 
                UnitPrice = 45.6000M, UnitsInStock = 26 },
              new { ProductID = 29, ProductName = "Thüringer Rostbratwurst", Category = "Meat/Poultry", 
                UnitPrice = 123.7900M, UnitsInStock = 0 },
              new { ProductID = 30, ProductName = "Nord-Ost Matjeshering", Category = "Seafood", 
                UnitPrice = 25.8900M, UnitsInStock = 10 },
              new { ProductID = 31, ProductName = "Gorgonzola Telino", Category = "Dairy Products", 
                UnitPrice = 12.5000M, UnitsInStock = 0 },
              new { ProductID = 32, ProductName = "Mascarpone Fabioli", Category = "Dairy Products", 
                UnitPrice = 32.0000M, UnitsInStock = 9 },
              new { ProductID = 33, ProductName = "Geitost", Category = "Dairy Products", 
                UnitPrice = 2.5000M, UnitsInStock = 112 },
              new { ProductID = 34, ProductName = "Sasquatch Ale", Category = "Beverages", 
                UnitPrice = 14.0000M, UnitsInStock = 111 },
              new { ProductID = 35, ProductName = "Steeleye Stout", Category = "Beverages", 
                UnitPrice = 18.0000M, UnitsInStock = 20 },
              new { ProductID = 36, ProductName = "Inlagd Sill", Category = "Seafood", 
                UnitPrice = 19.0000M, UnitsInStock = 112 },
              new { ProductID = 37, ProductName = "Gravad lax", Category = "Seafood", 
                UnitPrice = 26.0000M, UnitsInStock = 11 },
              new { ProductID = 38, ProductName = "Côte de Blaye", Category = "Beverages", 
                UnitPrice = 263.5000M, UnitsInStock = 17 },
              new { ProductID = 39, ProductName = "Chartreuse verte", Category = "Beverages", 
                UnitPrice = 18.0000M, UnitsInStock = 69 },
              new { ProductID = 40, ProductName = "Boston Crab Meat", Category = "Seafood", 
                UnitPrice = 18.4000M, UnitsInStock = 123 },
              new { ProductID = 41, ProductName = "Jack's New England Clam Chowder", Category = "Seafood", 
                UnitPrice = 9.6500M, UnitsInStock = 85 },
              new { ProductID = 42, ProductName = "Singaporean Hokkien Fried Mee", Category = "Grains/Cereals", 
                UnitPrice = 14.0000M, UnitsInStock = 26 },
              new { ProductID = 43, ProductName = "Ipoh Coffee", Category = "Beverages", 
                UnitPrice = 46.0000M, UnitsInStock = 17 },
              new { ProductID = 44, ProductName = "Gula Malacca", Category = "Condiments", 
                UnitPrice = 19.4500M, UnitsInStock = 27 },
              new { ProductID = 45, ProductName = "Rogede sild", Category = "Seafood", 
                UnitPrice = 9.5000M, UnitsInStock = 5 },
              new { ProductID = 46, ProductName = "Spegesild", Category = "Seafood", 
                UnitPrice = 12.0000M, UnitsInStock = 95 },
              new { ProductID = 47, ProductName = "Zaanse koeken", Category = "Confections", 
                UnitPrice = 9.5000M, UnitsInStock = 36 },
              new { ProductID = 48, ProductName = "Chocolade", Category = "Confections", 
                UnitPrice = 12.7500M, UnitsInStock = 15 },
              new { ProductID = 49, ProductName = "Maxilaku", Category = "Confections", 
                UnitPrice = 20.0000M, UnitsInStock = 10 },
              new { ProductID = 50, ProductName = "Valkoinen suklaa", Category = "Confections", 
                UnitPrice = 16.2500M, UnitsInStock = 65 },
              new { ProductID = 51, ProductName = "Manjimup Dried Apples", Category = "Produce", 
                UnitPrice = 53.0000M, UnitsInStock = 20 },
              new { ProductID = 52, ProductName = "Filo Mix", Category = "Grains/Cereals", 
                UnitPrice = 7.0000M, UnitsInStock = 38 },
              new { ProductID = 53, ProductName = "Perth Pasties", Category = "Meat/Poultry", 
                UnitPrice = 32.8000M, UnitsInStock = 0 },
              new { ProductID = 54, ProductName = "Tourtière", Category = "Meat/Poultry", 
                UnitPrice = 7.4500M, UnitsInStock = 21 },
              new { ProductID = 55, ProductName = "Pâté chinois", Category = "Meat/Poultry", 
                UnitPrice = 24.0000M, UnitsInStock = 115 },
              new { ProductID = 56, ProductName = "Gnocchi di nonna Alice", Category = "Grains/Cereals", 
                UnitPrice = 38.0000M, UnitsInStock = 21 },
              new { ProductID = 57, ProductName = "Ravioli Angelo", Category = "Grains/Cereals", 
                UnitPrice = 19.5000M, UnitsInStock = 36 },
              new { ProductID = 58, ProductName = "Escargots de Bourgogne", Category = "Seafood", 
                UnitPrice = 13.2500M, UnitsInStock = 62 },
              new { ProductID = 59, ProductName = "Raclette Courdavault", Category = "Dairy Products", 
                UnitPrice = 55.0000M, UnitsInStock = 79 },
              new { ProductID = 60, ProductName = "Camembert Pierrot", Category = "Dairy Products", 
                UnitPrice = 34.0000M, UnitsInStock = 19 },
              new { ProductID = 61, ProductName = "Sirop d'érable", Category = "Condiments", 
                UnitPrice = 28.5000M, UnitsInStock = 113 },
              new { ProductID = 62, ProductName = "Tarte au sucre", Category = "Confections", 
                UnitPrice = 49.3000M, UnitsInStock = 17 },
              new { ProductID = 63, ProductName = "Vegie-spread", Category = "Condiments", 
                UnitPrice = 43.9000M, UnitsInStock = 24 },
              new { ProductID = 64, ProductName = "Wimmers gute Semmelknödel", Category = "Grains/Cereals", 
                UnitPrice = 33.2500M, UnitsInStock = 22 },
              new { ProductID = 65, ProductName = "Louisiana Fiery Hot Pepper Sauce", Category = "Condiments", 
                UnitPrice = 21.0500M, UnitsInStock = 76 },
              new { ProductID = 66, ProductName = "Louisiana Hot Spiced Okra", Category = "Condiments", 
                UnitPrice = 17.0000M, UnitsInStock = 4 },
              new { ProductID = 67, ProductName = "Laughing Lumberjack Lager", Category = "Beverages", 
                UnitPrice = 14.0000M, UnitsInStock = 52 },
              new { ProductID = 68, ProductName = "Scottish Longbreads", Category = "Confections", 
                UnitPrice = 12.5000M, UnitsInStock = 6 },
              new { ProductID = 69, ProductName = "Gudbrandsdalsost", Category = "Dairy Products", 
                UnitPrice = 36.0000M, UnitsInStock = 26 },
              new { ProductID = 70, ProductName = "Outback Lager", Category = "Beverages", 
                UnitPrice = 15.0000M, UnitsInStock = 15 },
              new { ProductID = 71, ProductName = "Flotemysost", Category = "Dairy Products", 
                UnitPrice = 21.5000M, UnitsInStock = 26 },
              new { ProductID = 72, ProductName = "Mozzarella di Giovanni", Category = "Dairy Products", 
                UnitPrice = 34.8000M, UnitsInStock = 14 },
              new { ProductID = 73, ProductName = "Röd Kaviar", Category = "Seafood", 
                UnitPrice = 15.0000M, UnitsInStock = 101 },
              new { ProductID = 74, ProductName = "Longlife Tofu", Category = "Produce", 
                UnitPrice = 10.0000M, UnitsInStock = 4 },
              new { ProductID = 75, ProductName = "Rhönbräu Klosterbier", Category = "Beverages", 
                UnitPrice = 7.7500M, UnitsInStock = 125 },
              new { ProductID = 76, ProductName = "Lakkalikööri", Category = "Beverages", 
                UnitPrice = 18.0000M, UnitsInStock = 57 },
              new { ProductID = 77, ProductName = "Original Frankfurter grüne Soße", Category = "Condiments", 
                UnitPrice = 13.0000M, UnitsInStock = 32 }
            };

            foreach (var x in productList
Download .txt
gitextract_k3w_f6vi/

├── .gitignore
├── LICENSE.md
├── README.md
├── SDK/
│   ├── .gitignore
│   ├── README.md
│   ├── Samples/
│   │   ├── KitchenSink/
│   │   │   ├── AgentIntegration.cs
│   │   │   ├── Api.cs
│   │   │   ├── KitchenSink.workbook
│   │   │   ├── KitchenSinkIntegration.csproj
│   │   │   ├── KitchenSinkIntegration.js
│   │   │   ├── KitchenSinkIntegration.sln
│   │   │   └── Person.cs
│   │   └── XamarinInteractive.targets
│   └── typings/
│       └── xamarin-interactive.d.ts
├── android/
│   ├── README.md
│   ├── getting-started/
│   │   ├── AndroidAppBasics.workbook
│   │   ├── hello-android-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── user-interface/
│       ├── 2D-drawing.workbook
│       ├── AutoCompleteTextView.workbook
│       ├── PropertyAnimation.workbook
│       ├── listview.workbook
│       ├── meta.json
│       ├── popupmenus.workbook
│       ├── spinner.workbook
│       ├── switch.workbook
│       └── views.workbook
├── azure/
│   ├── cogs/
│   │   ├── emotion.workbook/
│   │   │   ├── employees.csx
│   │   │   └── index.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── tryazure/
│       ├── TryAzure-Mac.workbook
│       ├── TryAzure-WPF.workbook
│       ├── TryAzure-iOS.workbook
│       └── meta.json
├── charts/
│   ├── meta.json
│   ├── oxyplot/
│   │   ├── OxyPlot.workbook
│   │   └── meta.json
│   └── xplot/
│       ├── XPlot.workbook
│       └── meta.json
├── csharp/
│   ├── async/
│   │   ├── README.md
│   │   ├── async-await-wpf.workbook
│   │   ├── async-await.workbook
│   │   └── meta.json
│   ├── collections/
│   │   ├── README.md
│   │   ├── arrays.workbook
│   │   └── meta.json
│   ├── csharp6/
│   │   ├── README.md
│   │   ├── csharp6.workbook
│   │   └── meta.json
│   ├── csharp7/
│   │   ├── csharp7.workbook
│   │   ├── index.workbook
│   │   └── meta.json
│   ├── linq/
│   │   ├── 101-linq-examples.workbook/
│   │   │   ├── 101_Linq_Examples.csx
│   │   │   ├── Customers.xml
│   │   │   └── index.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── roslyn/
│       ├── meta.json
│       └── roslyn-syntax-trees.workbook/
│           └── index.workbook
├── graphics/
│   ├── meta.json
│   ├── skiasharp/
│   │   ├── colors/
│   │   │   └── colors.workbook/
│   │   │       └── index.workbook
│   │   ├── images/
│   │   │   └── images.workbook/
│   │   │       └── index.workbook
│   │   ├── introduction/
│   │   │   └── introduction.workbook/
│   │   │       └── index.workbook
│   │   ├── logo/
│   │   │   └── skialogo-ios.workbook/
│   │   │       └── index.workbook
│   │   ├── meta.json
│   │   └── pixmap/
│   │       └── pixmap.workbook/
│   │           └── index.workbook
│   ├── tiny-renderer/
│   │   ├── README.md
│   │   ├── Renderer/
│   │   │   ├── Listings/
│   │   │   │   ├── ListingTexture.cs
│   │   │   │   └── ListingZBuffer.cs
│   │   │   ├── Program.cs
│   │   │   ├── Properties/
│   │   │   │   └── AssemblyInfo.cs
│   │   │   ├── Renderer.csproj
│   │   │   ├── Renderer.sln
│   │   │   ├── Tests/
│   │   │   │   ├── GouraudShaderFixture.cs
│   │   │   │   ├── MatrixFixture.cs
│   │   │   │   ├── ModelFixture.cs
│   │   │   │   └── VectorFixture.cs
│   │   │   ├── WorkbookItems/
│   │   │   │   ├── Geometry.cs
│   │   │   │   ├── Image.cs
│   │   │   │   ├── Matrix.cs
│   │   │   │   ├── Model.cs
│   │   │   │   ├── Shaders.cs
│   │   │   │   └── Utils.cs
│   │   │   └── packages.config
│   │   ├── lesson1.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   └── obj/
│   │   │       └── african_head.obj
│   │   ├── lesson2.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   └── obj/
│   │   │       └── african_head.obj
│   │   ├── lesson3.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       └── african_head_spec.tga
│   │   ├── lesson4.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   └── obj/
│   │   │       └── cube.obj
│   │   ├── lesson5.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       └── african_head_spec.tga
│   │   ├── lesson6.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       ├── african_head_spec.tga
│   │   │       ├── diablo3-total-occlusion.tga
│   │   │       ├── diablo3_pose.obj
│   │   │       ├── diablo3_pose_diffuse.tga
│   │   │       ├── diablo3_pose_glow.tga
│   │   │       ├── diablo3_pose_nm.tga
│   │   │       ├── diablo3_pose_nm_tangent.tga
│   │   │       └── diablo3_pose_spec.tga
│   │   ├── lesson6bis.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   ├── lesson6.workbook
│   │   │   ├── lesson6bis.csx
│   │   │   └── obj/
│   │   │       ├── african_head.obj
│   │   │       ├── african_head_diffuse.tga
│   │   │       ├── african_head_nm.tga
│   │   │       ├── african_head_nm_tangent.tga
│   │   │       └── african_head_spec.tga
│   │   ├── lesson7.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   ├── lesson6.workbook
│   │   │   ├── lesson6bis.csx
│   │   │   ├── lesson6bis.workbook
│   │   │   └── obj/
│   │   │       ├── diablo3-total-occlusion.tga
│   │   │       ├── diablo3_pose.obj
│   │   │       ├── diablo3_pose_diffuse.tga
│   │   │       ├── diablo3_pose_glow.tga
│   │   │       ├── diablo3_pose_nm.tga
│   │   │       ├── diablo3_pose_nm_tangent.tga
│   │   │       └── diablo3_pose_spec.tga
│   │   ├── lesson8.workbook/
│   │   │   ├── Geometry.csx
│   │   │   ├── Image.csx
│   │   │   ├── ImageResultHandler.csx
│   │   │   ├── LICENSE.txt
│   │   │   ├── Matrix.csx
│   │   │   ├── Model.csx
│   │   │   ├── WpfImageResultHandler.csx
│   │   │   ├── index.workbook
│   │   │   ├── lesson1.csx
│   │   │   ├── lesson1.workbook
│   │   │   ├── lesson2.csx
│   │   │   ├── lesson2.workbook
│   │   │   ├── lesson3.csx
│   │   │   ├── lesson3.workbook
│   │   │   ├── lesson4.csx
│   │   │   ├── lesson4.workbook
│   │   │   ├── lesson5.csx
│   │   │   ├── lesson5.workbook
│   │   │   ├── lesson6.csx
│   │   │   ├── lesson6.workbook
│   │   │   ├── lesson6bis.csx
│   │   │   ├── lesson6bis.workbook
│   │   │   ├── lesson7.workbook
│   │   │   └── obj/
│   │   │       ├── diablo3-total-occlusion.tga
│   │   │       ├── diablo3_pose.obj
│   │   │       ├── diablo3_pose_diffuse.tga
│   │   │       ├── diablo3_pose_glow.tga
│   │   │       ├── diablo3_pose_nm.tga
│   │   │       ├── diablo3_pose_nm_tangent.tga
│   │   │       └── diablo3_pose_spec.tga
│   │   └── meta.json
│   └── urhosharp/
│       ├── .gitignore
│       ├── animated-model/
│       │   └── animated-model.workbook/
│       │       ├── Data/
│       │       │   ├── Animations/
│       │       │   │   ├── Mutant_Block_LY.ani
│       │       │   │   ├── Mutant_Death.ani
│       │       │   │   ├── Mutant_HipHop1.ani
│       │       │   │   ├── Mutant_HitHead_LY.ani
│       │       │   │   ├── Mutant_Idle0.ani
│       │       │   │   ├── Mutant_Idle1.ani
│       │       │   │   ├── Mutant_Jump.ani
│       │       │   │   ├── Mutant_Jump1.ani
│       │       │   │   ├── Mutant_JumpAttack.ani
│       │       │   │   ├── Mutant_JumpAttack_RM.ani
│       │       │   │   ├── Mutant_JumpStop.ani
│       │       │   │   ├── Mutant_Kick.ani
│       │       │   │   ├── Mutant_Punch.ani
│       │       │   │   ├── Mutant_Run.ani
│       │       │   │   ├── Mutant_Swipe.ani
│       │       │   │   ├── Mutant_Throw_LY.ani
│       │       │   │   ├── Mutant_Walk.ani
│       │       │   │   └── Mutant_Wave_LY.ani
│       │       │   ├── License.txt
│       │       │   ├── Materials/
│       │       │   │   └── mutant_M.xml
│       │       │   └── Models/
│       │       │       └── Mutant.mdl
│       │       └── index.workbook
│       ├── barchart/
│       │   └── charts.workbook/
│       │       └── index.workbook
│       ├── building-polyhedra/
│       │   └── BuildingPolyhedra.workbook/
│       │       ├── CreateModel.csx
│       │       ├── UrhoSettings.csx
│       │       └── index.workbook
│       ├── circle-of-life/
│       │   └── CircleOfLife.workbook/
│       │       ├── Data/
│       │       │   ├── Materials/
│       │       │   │   └── phong1.xml
│       │       │   └── monkey.mdl
│       │       └── index.workbook
│       ├── compound-shapes/
│       │   └── CreatingUrhoCompoundShapes.workbook/
│       │       └── index.workbook
│       ├── coordinates/
│       │   └── ExploringUrhoCoordinates.workbook/
│       │       └── index.workbook
│       ├── custom-geometries/
│       │   └── CustomGeometries.workbook/
│       │       ├── CreateModel.csx
│       │       └── index.workbook
│       ├── meta.json
│       ├── mobius-strip-speedway/
│       │   └── MobiusStripSpeedway.workbook/
│       │       ├── Data/
│       │       │   ├── BlueRacer/
│       │       │   │   ├── Materials/
│       │       │   │   │   ├── Material1.xml
│       │       │   │   │   ├── White.xml
│       │       │   │   │   ├── White_0.xml
│       │       │   │   │   ├── White_1.xml
│       │       │   │   │   ├── White_10.xml
│       │       │   │   │   ├── White_11.xml
│       │       │   │   │   ├── White_12.xml
│       │       │   │   │   ├── White_13.xml
│       │       │   │   │   ├── White_14.xml
│       │       │   │   │   ├── White_15.xml
│       │       │   │   │   ├── White_16.xml
│       │       │   │   │   ├── White_17.xml
│       │       │   │   │   ├── White_18.xml
│       │       │   │   │   ├── White_19.xml
│       │       │   │   │   ├── White_2.xml
│       │       │   │   │   ├── White_20.xml
│       │       │   │   │   ├── White_21.xml
│       │       │   │   │   ├── White_22.xml
│       │       │   │   │   ├── White_3.xml
│       │       │   │   │   ├── White_4.xml
│       │       │   │   │   ├── White_5.xml
│       │       │   │   │   ├── White_6.xml
│       │       │   │   │   ├── White_7.xml
│       │       │   │   │   ├── White_8.xml
│       │       │   │   │   └── White_9.xml
│       │       │   │   ├── Models/
│       │       │   │   │   ├── Object.1.mdl
│       │       │   │   │   ├── Object.10.mdl
│       │       │   │   │   ├── Object.11.mdl
│       │       │   │   │   ├── Object.12.mdl
│       │       │   │   │   ├── Object.13.mdl
│       │       │   │   │   ├── Object.14.mdl
│       │       │   │   │   ├── Object.15.mdl
│       │       │   │   │   ├── Object.16.mdl
│       │       │   │   │   ├── Object.17.mdl
│       │       │   │   │   ├── Object.18.mdl
│       │       │   │   │   ├── Object.19.mdl
│       │       │   │   │   ├── Object.2.mdl
│       │       │   │   │   ├── Object.20.mdl
│       │       │   │   │   ├── Object.21.mdl
│       │       │   │   │   ├── Object.22.mdl
│       │       │   │   │   ├── Object.23.mdl
│       │       │   │   │   ├── Object.24.mdl
│       │       │   │   │   ├── Object.25.mdl
│       │       │   │   │   ├── Object.26.mdl
│       │       │   │   │   ├── Object.27.mdl
│       │       │   │   │   ├── Object.28.mdl
│       │       │   │   │   ├── Object.29.mdl
│       │       │   │   │   ├── Object.3.mdl
│       │       │   │   │   ├── Object.30.mdl
│       │       │   │   │   ├── Object.31.mdl
│       │       │   │   │   ├── Object.32.mdl
│       │       │   │   │   ├── Object.33.mdl
│       │       │   │   │   ├── Object.34.mdl
│       │       │   │   │   ├── Object.35.mdl
│       │       │   │   │   ├── Object.36.mdl
│       │       │   │   │   ├── Object.37.mdl
│       │       │   │   │   ├── Object.38.mdl
│       │       │   │   │   ├── Object.39.mdl
│       │       │   │   │   ├── Object.4.mdl
│       │       │   │   │   ├── Object.40.mdl
│       │       │   │   │   ├── Object.41.mdl
│       │       │   │   │   ├── Object.42.mdl
│       │       │   │   │   ├── Object.43.mdl
│       │       │   │   │   ├── Object.44.mdl
│       │       │   │   │   ├── Object.45.mdl
│       │       │   │   │   ├── Object.46.mdl
│       │       │   │   │   ├── Object.47.mdl
│       │       │   │   │   ├── Object.48.mdl
│       │       │   │   │   ├── Object.49.mdl
│       │       │   │   │   ├── Object.5.mdl
│       │       │   │   │   ├── Object.50.mdl
│       │       │   │   │   ├── Object.51.mdl
│       │       │   │   │   ├── Object.52.mdl
│       │       │   │   │   ├── Object.53.mdl
│       │       │   │   │   ├── Object.54.mdl
│       │       │   │   │   ├── Object.55.mdl
│       │       │   │   │   ├── Object.56.mdl
│       │       │   │   │   ├── Object.57.mdl
│       │       │   │   │   ├── Object.58.mdl
│       │       │   │   │   ├── Object.59.mdl
│       │       │   │   │   ├── Object.6.mdl
│       │       │   │   │   ├── Object.7.mdl
│       │       │   │   │   ├── Object.8.mdl
│       │       │   │   │   └── Object.9.mdl
│       │       │   │   └── node.xml
│       │       │   └── RedRolls/
│       │       │       ├── Materials/
│       │       │       │   ├── White.xml
│       │       │       │   ├── White_0.xml
│       │       │       │   ├── White_1.xml
│       │       │       │   ├── White_10.xml
│       │       │       │   ├── White_11.xml
│       │       │       │   ├── White_12.xml
│       │       │       │   ├── White_13.xml
│       │       │       │   ├── White_14.xml
│       │       │       │   ├── White_15.xml
│       │       │       │   ├── White_16.xml
│       │       │       │   ├── White_17.xml
│       │       │       │   ├── White_2.xml
│       │       │       │   ├── White_3.xml
│       │       │       │   ├── White_4.xml
│       │       │       │   ├── White_5.xml
│       │       │       │   ├── White_6.xml
│       │       │       │   ├── White_7.xml
│       │       │       │   ├── White_8.xml
│       │       │       │   └── White_9.xml
│       │       │       ├── Models/
│       │       │       │   ├── Object.1.mdl
│       │       │       │   ├── Object.10.mdl
│       │       │       │   ├── Object.11.mdl
│       │       │       │   ├── Object.12.mdl
│       │       │       │   ├── Object.13.mdl
│       │       │       │   ├── Object.14.mdl
│       │       │       │   ├── Object.15.mdl
│       │       │       │   ├── Object.16.mdl
│       │       │       │   ├── Object.17.mdl
│       │       │       │   ├── Object.18.mdl
│       │       │       │   ├── Object.19.mdl
│       │       │       │   ├── Object.2.mdl
│       │       │       │   ├── Object.20.mdl
│       │       │       │   ├── Object.21.mdl
│       │       │       │   ├── Object.22.mdl
│       │       │       │   ├── Object.23.mdl
│       │       │       │   ├── Object.24.mdl
│       │       │       │   ├── Object.25.mdl
│       │       │       │   ├── Object.26.mdl
│       │       │       │   ├── Object.27.mdl
│       │       │       │   ├── Object.28.mdl
│       │       │       │   ├── Object.29.mdl
│       │       │       │   ├── Object.3.mdl
│       │       │       │   ├── Object.30.mdl
│       │       │       │   ├── Object.31.mdl
│       │       │       │   ├── Object.32.mdl
│       │       │       │   ├── Object.33.mdl
│       │       │       │   ├── Object.34.mdl
│       │       │       │   ├── Object.35.mdl
│       │       │       │   ├── Object.36.mdl
│       │       │       │   ├── Object.37.mdl
│       │       │       │   ├── Object.38.mdl
│       │       │       │   ├── Object.39.mdl
│       │       │       │   ├── Object.4.mdl
│       │       │       │   ├── Object.40.mdl
│       │       │       │   ├── Object.41.mdl
│       │       │       │   ├── Object.42.mdl
│       │       │       │   ├── Object.43.mdl
│       │       │       │   ├── Object.44.mdl
│       │       │       │   ├── Object.45.mdl
│       │       │       │   ├── Object.46.mdl
│       │       │       │   ├── Object.47.mdl
│       │       │       │   ├── Object.48.mdl
│       │       │       │   ├── Object.49.mdl
│       │       │       │   ├── Object.5.mdl
│       │       │       │   ├── Object.50.mdl
│       │       │       │   ├── Object.51.mdl
│       │       │       │   ├── Object.52.mdl
│       │       │       │   ├── Object.53.mdl
│       │       │       │   ├── Object.54.mdl
│       │       │       │   ├── Object.55.mdl
│       │       │       │   ├── Object.56.mdl
│       │       │       │   ├── Object.57.mdl
│       │       │       │   ├── Object.58.mdl
│       │       │       │   ├── Object.59.mdl
│       │       │       │   ├── Object.6.mdl
│       │       │       │   ├── Object.60.mdl
│       │       │       │   ├── Object.7.mdl
│       │       │       │   ├── Object.8.mdl
│       │       │       │   └── Object.9.mdl
│       │       │       └── node.xml
│       │       └── index.workbook
│       ├── physics/
│       │   └── physics.workbook/
│       │       ├── Data/
│       │       │   └── bucket.mdl
│       │       └── index.workbook
│       └── planetearth/
│           └── planetearth.workbook/
│               ├── Data/
│               │   ├── Materials/
│               │   │   └── SatNoTexture.xml
│               │   ├── Models/
│               │   │   └── BigSatellite.mdl
│               │   ├── RenderPaths/
│               │   │   └── Outline.xml
│               │   ├── Shaders/
│               │   │   └── GLSL/
│               │   │       └── Outline.glsl
│               │   ├── Techniques/
│               │   │   ├── NoTextureOutline.xml
│               │   │   └── TextureOutline.xml
│               │   └── Textures/
│               │       └── License.txt
│               └── index.workbook
├── ios/
│   ├── README.md
│   ├── getting-started/
│   │   ├── Learning-iOS.workbook
│   │   ├── hello-ios-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   ├── platform-features/
│   │   ├── auto-layout/
│   │   │   └── programmatical-constraints.workbook
│   │   ├── meta.json
│   │   ├── scenekit/
│   │   │   ├── README.md
│   │   │   ├── exploring-scenekit.workbook/
│   │   │   │   └── index.workbook
│   │   │   └── scngeometrysource.workbook/
│   │   │       └── index.workbook
│   │   ├── texttospeech/
│   │   │   └── TextToSpeech.workbook
│   │   ├── touchid/
│   │   │   └── TouchID.workbook
│   │   └── widecolor/
│   │       └── widecolor.workbook/
│   │           └── index.workbook
│   └── user-interface/
│       ├── UIButton/
│       │   └── uibutton.workbook/
│       │       └── index.workbook
│       ├── UIImage/
│       │   └── uiimage.workbook/
│       │       └── index.workbook
│       ├── UILabel/
│       │   └── uilabel.workbook/
│       │       └── index.workbook
│       ├── UINavigationController/
│       │   ├── README.md
│       │   └── uinavigationcontroller.workbook/
│       │       ├── Hierarchical-Navigation.csx
│       │       └── index.workbook
│       ├── UISwitch/
│       │   └── index.workbook
│       ├── UITableView/
│       │   └── uitableview.workbook/
│       │       └── index.workbook
│       ├── alerts/
│       │   └── alert-controller.workbook/
│       │       ├── alert_controller.csx
│       │       └── index.workbook
│       ├── meta.json
│       ├── uitableview-1/
│       │   ├── README.md
│       │   └── uitableview1.workbook/
│       │       └── index.workbook
│       └── web-views/
│           └── web-views.workbook/
│               ├── index.workbook
│               └── tabbar.csx
├── mac/
│   ├── README.md
│   ├── getting-started/
│   │   ├── README.md
│   │   ├── hello-mac-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── user-interface/
│       ├── README.md
│       ├── meta.json
│       ├── outlineview/
│       │   ├── NSOutlineView.workbook
│       │   └── README.md
│       ├── segues/
│       │   ├── README.md
│       │   └── Segues.workbook/
│       │       ├── Main.storyboard
│       │       ├── Main.storyboardc/
│       │       │   ├── 4cK-Eu-ujv-view-YYD-CQ-DLY.nib
│       │       │   ├── CCf-Sq-ZKC-view-E33-5d-PF3.nib
│       │       │   ├── Info.plist
│       │       │   ├── Kgw-Zr-aQ8-view-3jo-us-oYx.nib
│       │       │   ├── MainMenu.nib
│       │       │   ├── NSViewController-CCf-Sq-ZKC.nib
│       │       │   ├── NSViewController-Kgw-Zr-aQ8.nib
│       │       │   ├── NSViewController-hlZ-SX-RFF.nib
│       │       │   ├── NSWindowController-B8D-0N-5wS.nib
│       │       │   ├── NSWindowController-plf-cC-dqu.nib
│       │       │   ├── XdO-WJ-HvK-view-Tof-WT-yQ6.nib
│       │       │   ├── XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
│       │       │   └── hlZ-SX-RFF-view-404-bt-De6.nib
│       │       ├── StoryboardResources.csx
│       │       ├── Walkthrough.storyboard
│       │       ├── Walkthrough.storyboardc/
│       │       │   ├── 4cK-Eu-ujv-view-YYD-CQ-DLY.nib
│       │       │   ├── CCf-Sq-ZKC-view-E33-5d-PF3.nib
│       │       │   ├── Info.plist
│       │       │   ├── Kgw-Zr-aQ8-view-3jo-us-oYx.nib
│       │       │   ├── MainMenu.nib
│       │       │   ├── NSViewController-CCf-Sq-ZKC.nib
│       │       │   ├── NSViewController-Kgw-Zr-aQ8.nib
│       │       │   ├── NSViewController-hlZ-SX-RFF.nib
│       │       │   ├── NSWindowController-B8D-0N-5wS.nib
│       │       │   ├── NSWindowController-plf-cC-dqu.nib
│       │       │   ├── XdO-WJ-HvK-view-Tof-WT-yQ6.nib
│       │       │   ├── XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
│       │       │   └── hlZ-SX-RFF-view-404-bt-De6.nib
│       │       └── index.workbook
│       ├── tableview/
│       │   ├── NSTableView.workbook
│       │   └── README.md
│       ├── toolbars/
│       │   ├── README.md
│       │   └── toolbars.workbook/
│       │       ├── index.workbook
│       │       └── toolbar-resources.csx
│       ├── ui-in-code/
│       │   ├── README.md
│       │   └── codebasedui.workbook/
│       │       └── index.workbook
│       └── webbrowser/
│           ├── README.md
│           └── webbrowser.workbook/
│               ├── Main.storyboard
│               ├── Main.storyboardc/
│               │   ├── Info.plist
│               │   ├── MainMenu.nib
│               │   ├── MainViewController.nib
│               │   ├── MainWindowController.nib
│               │   └── XfG-lQ-9wD-view-m2S-Jp-Qdl.nib
│               ├── StoryboardResources.csx
│               └── index.workbook
├── machine-learning/
│   └── ML - Getting Started - Sentiment Analysis.workbook/
│       ├── index.workbook
│       ├── ml-sent.csx
│       ├── sentiment-imdb-train.txt
│       └── sentiment-yelp-test.txt
├── workbooks/
│   ├── README.md
│   ├── getting-started/
│   │   ├── meta.json
│   │   └── welcome.workbook
│   ├── meta.json
│   └── visualizers/
│       ├── README.md
│       ├── Visualizers-console.workbook
│       ├── Visualizers-ios.workbook
│       ├── Visualizers-mac.workbook
│       ├── Visualizers-wpf.workbook
│       └── meta.json
├── wpf/
│   ├── README.md
│   ├── getting-started/
│   │   ├── HelloWPF.workbook
│   │   ├── hello-wpf-workbook.workbook
│   │   └── meta.json
│   ├── meta.json
│   └── user-interface/
│       ├── graphics/
│       │   └── PenroseTriangle.workbook/
│       │       └── index.workbook
│       └── meta.json
└── xamarin-forms/
    ├── README.md
    ├── advanced/
    │   ├── MandelbrotTouch.workbook/
    │   │   ├── BitmapInfo.csx
    │   │   ├── BmpMaker.csx
    │   │   ├── Complex.csx
    │   │   ├── FormsInit.csx
    │   │   ├── Mandelbrot.png.txt
    │   │   ├── MandelbrotModel.csx
    │   │   └── index.workbook
    │   ├── RPNCalculator/
    │   │   ├── README.md
    │   │   ├── RpnCalculator-ios.workbook
    │   │   └── RpnCalculator.workbook
    │   └── meta.json
    ├── application-fundamentals/
    │   ├── database/
    │   │   └── database.workbook/
    │   │       ├── FormsInit.csx
    │   │       └── index.workbook
    │   ├── files/
    │   │   └── files.workbook/
    │   │       ├── FormsInit.csx
    │   │       └── index.workbook
    │   ├── hierarchical-navigation/
    │   │   └── hierarchical-navigation.workbook/
    │   │       ├── FormsInit.csx
    │   │       └── index.workbook
    │   ├── meta.json
    │   └── text-to-speech/
    │       └── text-to-speech.workbook/
    │           ├── FormsInit.csx
    │           └── index.workbook
    ├── getting-started/
    │   ├── GettingStartedWithXamarinForms-ios.workbook
    │   ├── GettingStartedWithXamarinForms.workbook
    │   └── meta.json
    ├── meta.json
    └── user-interface/
        ├── alerts/
        │   └── alerts.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── button/
        │   └── button.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── editor/
        │   └── editor.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── entry/
        │   └── entry.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── image/
        │   └── image.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── label/
        │   └── label.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── layout-options/
        │   └── layout-options.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── listview/
        │   ├── ListView.workbook
        │   ├── ListView1-android.workbook
        │   └── ListView1-ios.workbook
        ├── map/
        │   └── map.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── margins-padding/
        │   └── margins-and-padding/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── meta.json
        ├── picker/
        │   └── picker.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── slider/
        │   └── slider.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── stacklayout/
        │   └── stacklayout.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── switch/
        │   └── switch.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── tabbedpage/
        │   └── tabbedpage.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        ├── webview/
        │   └── webview.workbook/
        │       ├── FormsInit.csx
        │       └── index.workbook
        └── xaml/
            └── LoadXaml.workbook
Download .txt
SYMBOL INDEX (206 symbols across 18 files)

FILE: SDK/Samples/KitchenSink/AgentIntegration.cs
  class AgentIntegration (line 12) | class AgentIntegration : IAgentIntegration
    method IntegrateWith (line 16) | public void IntegrateWith (IAgent agent)
    class SampleRepresentationProvider (line 21) | class SampleRepresentationProvider : RepresentationProvider
      method HasSensibleEnumerator (line 23) | public override bool HasSensibleEnumerator (IEnumerable enumerable)
      method ProvideRepresentations (line 33) | public override IEnumerable<object> ProvideRepresentations (object obj)

FILE: SDK/Samples/KitchenSink/Api.cs
  class KitchenSink (line 5) | public static class KitchenSink
    method RandomColor (line 9) | public static Color RandomColor ()

FILE: SDK/Samples/KitchenSink/KitchenSinkIntegration.js
  function PersonRenderer (line 4) | function PersonRenderer () {

FILE: SDK/Samples/KitchenSink/Person.cs
  class Person (line 7) | public sealed class Person : ISerializableObject
    method Person (line 11) | public Person (string name)
    method Serialize (line 19) | void ISerializableObject.Serialize (ObjectSerializer serializer)

FILE: SDK/typings/xamarin-interactive.d.ts
  type CultureInfo (line 6) | interface CultureInfo {
  type ManagedObject (line 14) | interface ManagedObject {
  type RendererRepresentationOptions (line 26) | enum RendererRepresentationOptions {
  type RendererRepresentation (line 58) | interface RendererRepresentation {
  type RenderTarget (line 81) | interface RenderTarget {
  type RenderState (line 103) | interface RenderState {
  type Renderer (line 123) | interface Renderer {
  class RendererRegistry (line 168) | class RendererRegistry {

FILE: graphics/tiny-renderer/Renderer/Listings/ListingTexture.cs
  class ListingTexture (line 7) | static class ListingTexture
    method Execute (line 14) | public static void Execute (Model model, Image texture)

FILE: graphics/tiny-renderer/Renderer/Listings/ListingZBuffer.cs
  class ListingZBuffer (line 7) | static class ListingZBuffer
    method Execute (line 14) | public static void Execute (Model model)

FILE: graphics/tiny-renderer/Renderer/Program.cs
  class MainClass (line 8) | class MainClass
    method Main (line 57) | public static void Main (string [] args)
    method ScreenSpaceAOListing (line 91) | static void ScreenSpaceAOListing ()
    method AOShaderListing (line 123) | static void AOShaderListing ()
    method AmbientListing (line 129) | static void AmbientListing ()
    method DepthShaderListing (line 190) | static void DepthShaderListing ()
    method TangetShaderListing (line 205) | static void TangetShaderListing ()
    method SpecularShaderListing (line 212) | static void SpecularShaderListing ()
    method RunSpec (line 218) | static void RunSpec (Model model, Image texture, Image nm, Image sm, s...
    method NormalMapListing (line 224) | static void NormalMapListing ()
    method TextureShaderListing (line 230) | static void TextureShaderListing ()
    method GouraudShader6Listing (line 236) | static void GouraudShader6Listing ()
    method GouraudShaderListing (line 242) | static void GouraudShaderListing ()
    method Render (line 248) | static RenderResult Render (Model model, IShader shader, string path)
    method Render (line 257) | static RenderResult Render (Model model, IShader shader)
    class RenderResult (line 275) | class RenderResult
    method CameraMoveListing (line 281) | static void CameraMoveListing ()
    method ProjectionListing (line 307) | static void ProjectionListing ()
    method LightListing (line 337) | static void LightListing ()
    method TriangleListing (line 362) | static void TriangleListing ()

FILE: graphics/tiny-renderer/Renderer/Tests/GouraudShaderFixture.cs
  class GouraudShaderFixture (line 10) | [TestFixture]
    method Vertex (line 18) | [Test]

FILE: graphics/tiny-renderer/Renderer/Tests/MatrixFixture.cs
  class MatrixFixture (line 9) | [TestFixture]
    method InverseIdentity (line 12) | [Test]

FILE: graphics/tiny-renderer/Renderer/Tests/ModelFixture.cs
  class ModelUtils (line 7) | static class ModelUtils
    method GetModel1 (line 21) | public static Model GetModel1 ()
  class ModelFixture (line 27) | [TestFixture]
    method Normal (line 30) | [Test]

FILE: graphics/tiny-renderer/Renderer/Tests/VectorFixture.cs
  class VectorFixture (line 7) | [TestFixture]
    method Project3D (line 10) | [Test]
    method Embed4D_DefaultValue (line 21) | [Test]
    method Embed4D (line 33) | [Test]
    method VectorIndexer (line 45) | [Test]
    method Vector4_Divide (line 73) | [Test]
    method Vector4_Sub (line 85) | [Test]
    method Vector4_Norm (line 98) | [Test]
    method Vector4_Normalize (line 106) | [Test]

FILE: graphics/tiny-renderer/Renderer/WorkbookItems/Geometry.cs
  type Vec2f (line 5) | struct Vec2f
    method Normalize (line 23) | public Vec2f Normalize ()
    method Norm (line 28) | public float Norm ()
  type Vec3f (line 60) | public struct Vec3f
    method Normalize (line 85) | public Vec3f Normalize ()
    method Norm (line 90) | public float Norm ()
  type Vec4f (line 119) | struct Vec4f
    method Normalize (line 147) | public Vec4f Normalize ()
    method Norm (line 153) | public float Norm ()
  type Vec2i (line 174) | struct Vec2i
  type Vec3i (line 185) | struct Vec3i
  class Geometry (line 197) | static class Geometry
    method Cross (line 199) | public static Vec3f Cross (Vec3f l, Vec3f r)
    method Dot (line 208) | public static float Dot (Vec3f l, Vec3f r)
    method Embed4D (line 213) | public static Vec4f Embed4D (Vec3f v, float fill = 1)
    method Project2D (line 218) | public static Vec2f Project2D (Vec3f v)
    method Project2D (line 223) | public static Vec2f Project2D (Vec4f v)
    method Project3D (line 228) | public static Vec3f Project3D (Vec4f v)

FILE: graphics/tiny-renderer/Renderer/WorkbookItems/Image.cs
  type Format (line 7) | enum Format
  type Color (line 14) | struct Color
    method Color (line 37) | public Color (byte red, byte green, byte blue, byte alpha)
    method Color (line 42) | public Color (byte red, byte green, byte blue)
    method Color (line 47) | public Color (byte value)
    method Color (line 52) | public Color (int value, Format format)
  class Image (line 69) | class Image
    method Image (line 83) | public Image (int width, int height, Format format)
    method VerticalFlip (line 92) | public void VerticalFlip ()
    method Clear (line 110) | public void Clear ()
    method GetOffset (line 141) | int GetOffset (int x, int y)
    method WriteToFile (line 146) | public bool WriteToFile (string path, bool rle = true)
    method Load (line 168) | public static Image Load (string path)
    method WriteTo (line 205) | static void WriteTo (BinaryWriter writer, TGAHeader header)
    method ReadHeader (line 221) | static TGAHeader ReadHeader (BinaryReader reader)
    method UnloadRleData (line 240) | bool UnloadRleData (BinaryWriter writer)
    method LoadRleData (line 275) | void LoadRleData (BinaryReader reader)
    method DataTypeFor (line 309) | static DataType DataTypeFor (int bpp, bool rle)
  type TGAHeader (line 318) | struct TGAHeader
  type DataType (line 338) | public enum DataType : byte

FILE: graphics/tiny-renderer/Renderer/WorkbookItems/Matrix.cs
  type Matrix4 (line 5) | public struct Matrix4
    method Transpose (line 99) | public Matrix4 Transpose ()
    method Identity (line 110) | public static Matrix4 Identity ()
    method Zoom (line 115) | public static Matrix4 Zoom (float scale)
    method RotationZ (line 120) | public static Matrix4 RotationZ (float angle)
    method ToString (line 147) | public override string ToString ()
  type Matrix3 (line 159) | public struct Matrix3
    method Transpose (line 228) | public Matrix3 Transpose ()
    method SetColumn (line 237) | public void SetColumn (int col, Vec3f v)
    method SetRow (line 244) | public void SetRow (int row, Vec3f v)
    method ToString (line 251) | public override string ToString ()
  type Matrix2 (line 263) | public struct Matrix2
  class MatrixHelpers (line 314) | static class MatrixHelpers
    method TransposeInverse (line 382) | public static Matrix4 TransposeInverse (Matrix4 m)
    method Inverse (line 402) | public static Matrix4 Inverse (Matrix4 m)
    method Inverse (line 422) | public static Matrix3 Inverse (Matrix3 m)
    method Cofactor (line 442) | static Matrix4 Cofactor (Matrix4 m)
    method Cofactor (line 452) | static Matrix3 Cofactor (Matrix3 m)
    method Cofactor (line 462) | static float Cofactor (Matrix4 m, int row, int col)
    method Cofactor (line 468) | static float Cofactor (Matrix3 m, int row, int col)
    method Minor (line 474) | static Matrix3 Minor (Matrix4 m, int row, int col)
    method Minor (line 487) | static Matrix2 Minor (Matrix3 m, int row, int col)
    method Det (line 500) | static float Det (Matrix3 m)
    method Det (line 509) | static float Det (Matrix2 m)
    method Mult (line 514) | public static Vec3f Mult (Matrix3 m, Vec3f v)
    method Mult (line 523) | public static Vec4f Mult (Matrix4 m, Vec4f v)

FILE: graphics/tiny-renderer/Renderer/WorkbookItems/Model.cs
  type Face (line 8) | struct Face
  class Model (line 15) | class Model
    method FromFile (line 22) | public static Model FromFile (string path)
    method FromText (line 36) | public static Model FromText (string text)
    method ParseLine (line 48) | void ParseLine (string line)
    method Normal (line 76) | public Vec3f Normal (Face face, int nthvert)
    method Vertex (line 82) | public Vec3f Vertex (Face face, int nthvert)
    method GetUV (line 88) | public Vec3f GetUV (Face face, int nthvert)

FILE: graphics/tiny-renderer/Renderer/WorkbookItems/Shaders.cs
  type IShader (line 9) | interface IShader
    method Vertex (line 11) | Vec4f Vertex (Face face, int nthvert);
    method Fragment (line 12) | bool Fragment (Vec3f fragment, Vec3f bar, out Color color);
  class GouraudShader (line 16) | class GouraudShader : IShader
    method GouraudShader (line 26) | public GouraudShader (Model model, Matrix4 viewPort, Matrix4 projectio...
    method Vertex (line 33) | public virtual Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 41) | public virtual bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class GouraudShader6 (line 49) | class GouraudShader6 : GouraudShader
    method GouraudShader6 (line 51) | public GouraudShader6 (Model model, Matrix4 viewPort, Matrix4 projecti...
    method Fragment (line 56) | public override bool Fragment (Vec3f fragment, Vec3f bar, out Color co...
  class TextureShader (line 70) | class TextureShader : IShader
    method TextureShader (line 82) | public TextureShader (Model model, Matrix4 viewPort, Matrix4 projectio...
    method Vertex (line 90) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 100) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class NormalMapShader (line 113) | class NormalMapShader : IShader
    method NormalMapShader (line 127) | public NormalMapShader (Model model, Matrix4 viewport, Matrix4 project...
    method Vertex (line 139) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 145) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class SpecularShader (line 157) | class SpecularShader : IShader
    method SpecularShader (line 172) | public SpecularShader (Model model, Matrix4 viewport, Matrix4 projecti...
    method Vertex (line 185) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 191) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class TangentShader (line 213) | class TangentShader : IShader
    method TangentShader (line 237) | public TangentShader (Model model, Matrix4 viewport, Matrix4 projectio...
    method Vertex (line 252) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 265) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class DepthShader (line 294) | class DepthShader : IShader
    method DepthShader (line 303) | public DepthShader (Model model, Matrix4 transformation)
    method Vertex (line 309) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 316) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class ShadowShader (line 324) | class ShadowShader : IShader
    method ShadowShader (line 344) | public ShadowShader (Model model, Matrix4 viewport, Matrix4 projection...
    method Vertex (line 360) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 370) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class ZShader (line 398) | class ZShader : IShader
    method ZShader (line 405) | public ZShader (Model model, Matrix4 viewport, Matrix4 projection, Mat...
    method Vertex (line 411) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 416) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class OcclusionShader (line 423) | class OcclusionShader : IShader
    method OcclusionShader (line 434) | public OcclusionShader (Model model, Matrix4 viewport, Matrix4 project...
    method Vertex (line 444) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 450) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class AOShader (line 464) | class AOShader : IShader
    method AOShader (line 473) | public AOShader (Model model, Matrix4 viewport, Matrix4 projection, Ma...
    method Vertex (line 481) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 487) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class ZShader2 (line 500) | class ZShader2 : IShader
    method ZShader2 (line 505) | public ZShader2 (Model model, Matrix4 viewport, Matrix4 projection, Ma...
    method Vertex (line 511) | public Vec4f Vertex (Face face, int nthvert)
    method Fragment (line 516) | public bool Fragment (Vec3f fragment, Vec3f bar, out Color color)
  class ShaderUtils (line 525) | static class ShaderUtils
    method TransformFace (line 528) | public static Vec4f TransformFace (Model model, Face face, int nthvert...
    method UpdateVarayingUV (line 536) | public static void UpdateVarayingUV (Model model, Face face, int nthve...
    method CalcUV (line 544) | public static Vec2f CalcUV (Vec3f varU, Vec3f varV, Vec3f bar)
    method GetColor (line 553) | public static Color GetColor (Image texture, Vec2f uvf)
    method Transform (line 559) | public static Vec3f Transform (Matrix4 t, Vec3f v)
    method Normal (line 566) | public static Vec3f Normal (Image normalMap, Vec2f uvf)
    method Specular (line 579) | public static float Specular (Image specularMap, Vec2f uvf)
    method CalcXY (line 587) | public static Vec2i CalcXY (Image texture, Vec2f uvf)

FILE: graphics/tiny-renderer/Renderer/WorkbookItems/Utils.cs
  class Utils (line 7) | static class Utils
    method Barycentric (line 9) | public static Vec3f Barycentric (Vec3f a, Vec3f b, Vec3f c, Vec2i p)
    method Triangle (line 26) | public static void Triangle (Image image, Vec3f [] coordinates, Color ...
    method Barycentric (line 53) | public static Vec3f Barycentric (Vec2f a, Vec2f b, Vec2f c, Vec2f p)
    method Triangle (line 77) | public static void Triangle (Image image, Vec3f [] coordinates, Color ...
    method InitZBuffer (line 113) | public static float [] InitZBuffer (Image image)
    method Triangle (line 122) | public static void Triangle (Image image, Vec3f [] coordinates, Image ...
    method Box (line 161) | public static void Box (Vec4f [] pts, out Vec2i pMin, out Vec2i pMax)
    method Triangle (line 174) | public static void Triangle (Image image, Vec4f [] pts, IShader shader...
    method DegToRad (line 207) | public static float DegToRad (float degAngle)
    method Viewport (line 213) | public static Matrix4 Viewport (int x, int y, int w, int h)
    method Projection (line 229) | public static Matrix4 Projection (float coeff)
    method LookAt (line 237) | public static Matrix4 LookAt (Vec3f eye, Vec3f center, Vec3f up)
    method RandPointOnUnitSphere (line 256) | public static Vec3f RandPointOnUnitSphere ()
    method MaxElevationAngle (line 271) | public static float MaxElevationAngle (float [] zbuffer, Vec2f p, Vec2...
Condensed preview — 657 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,438K chars).
[
  {
    "path": ".gitignore",
    "chars": 55,
    "preview": ".DS_Store\n[Bb]in/\ngraphics/tiny-renderer/Renderer/obj/\n"
  },
  {
    "path": "LICENSE.md",
    "chars": 1172,
    "preview": "The code in this repository is licensed under the terms of the MIT license:\n\nThe MIT License (MIT)\nCopyright (c) 2016 Mi"
  },
  {
    "path": "README.md",
    "chars": 1091,
    "preview": "# Sample Workbooks\n\nThis repository contains workbooks to learn various APIs across\nAndroid, iOS and Windows.\n\n**If you "
  },
  {
    "path": "SDK/.gitignore",
    "chars": 18,
    "preview": "bin/\nobj/\n*.user*\n"
  },
  {
    "path": "SDK/README.md",
    "chars": 324,
    "preview": "# Custom Integrations with Xamarin Workbooks\n\nThis directory contains sample integrations and accompanying support mater"
  },
  {
    "path": "SDK/Samples/KitchenSink/AgentIntegration.cs",
    "chars": 1065,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nusing Xamarin.Interactive;\nusing Xamarin.Int"
  },
  {
    "path": "SDK/Samples/KitchenSink/Api.cs",
    "chars": 263,
    "preview": "using System;\n\nusing Xamarin.Interactive.Representations;\n\npublic static class KitchenSink\n{\n\tstatic readonly Random ra"
  },
  {
    "path": "SDK/Samples/KitchenSink/KitchenSink.workbook",
    "chars": 239,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: MacMobile\n---\n\n```csharp\n#r \"bin/KitchenSinkIntegration.dll\"\n```\n\n```csharp\nKitc"
  },
  {
    "path": "SDK/Samples/KitchenSink/KitchenSinkIntegration.csproj",
    "chars": 1926,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microso"
  },
  {
    "path": "SDK/Samples/KitchenSink/KitchenSinkIntegration.js",
    "chars": 1029,
    "preview": "console.log(\"hello from some third party code => %O\", xamarin.interactive)\n\nvar PersonRenderer = (function () {\n  funct"
  },
  {
    "path": "SDK/Samples/KitchenSink/KitchenSinkIntegration.sln",
    "chars": 626,
    "preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 2012\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-0"
  },
  {
    "path": "SDK/Samples/KitchenSink/Person.cs",
    "chars": 427,
    "preview": "using System;\n\nusing Xamarin.Interactive.Serialization;\n\nnamespace KitchenSinkIntegration\n{\n\tpublic sealed class Person"
  },
  {
    "path": "SDK/Samples/XamarinInteractive.targets",
    "chars": 560,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild"
  },
  {
    "path": "SDK/typings/xamarin-interactive.d.ts",
    "chars": 5002,
    "preview": "declare module \"xamarin/interactive/dotnet\" {\n  /**\n   * A .NET CultureInfo.\n   * See https://msdn.microsoft.com/en-us/l"
  },
  {
    "path": "android/README.md",
    "chars": 67,
    "preview": "Android Workbooks\n============\n\n* Getting Started\n* User Interface\n"
  },
  {
    "path": "android/getting-started/AndroidAppBasics.workbook",
    "chars": 6725,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# Android App Basics\n\nIn this interactive tutorial, yo"
  },
  {
    "path": "android/getting-started/hello-android-workbook.workbook",
    "chars": 264,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\n---\n\n# Android\n\n```csharp\nvar mainActivity = StartedActivities.First();\n"
  },
  {
    "path": "android/getting-started/meta.json",
    "chars": 121,
    "preview": "{\n  \"order\":{\n    \"AndroidAppBasics.workbook\":\"App Basics\",\n    \"hello-android-workbook.workbook\":\"Hello, Android\"\n  }\n}"
  },
  {
    "path": "android/meta.json",
    "chars": 99,
    "preview": "{\n  \"order\":{\n    \"getting-started\":\"Getting Started\",\n    \"user-interface\":\"User Interface\"\n  }\n}\n"
  },
  {
    "path": "android/user-interface/2D-drawing.workbook",
    "chars": 3001,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# 2D Graphics in Xamarin.Android\n\nIn this workbook, yo"
  },
  {
    "path": "android/user-interface/AutoCompleteTextView.workbook",
    "chars": 3321,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# AutoCompleteTextView\n\nThis guide will demonstrate ho"
  },
  {
    "path": "android/user-interface/PropertyAnimation.workbook",
    "chars": 4422,
    "preview": "```json\n{\"platform\":\"Android\",\"uti\":\"com.xamarin.workbook\",\"packages\":[]}\n```\n\n# Android View Property Animation\n\nIn thi"
  },
  {
    "path": "android/user-interface/listview.workbook",
    "chars": 3511,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# Using a ListView in Xamarin.Android\n\nThis guide will"
  },
  {
    "path": "android/user-interface/meta.json",
    "chars": 349,
    "preview": "{\n  \"order\":{\n    \"2D-drawing.workbook\":\"2D Drawing\",\n    \"AutoCompleteTextView.workbook\":\"AutoComplete Text View\",\n    "
  },
  {
    "path": "android/user-interface/popupmenus.workbook",
    "chars": 3614,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# Android Popup Menus\n\nA *Popup menu* is a menu that i"
  },
  {
    "path": "android/user-interface/spinner.workbook",
    "chars": 3693,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# Using a Spinner in Xamarin.Android\n\nThis guide will "
  },
  {
    "path": "android/user-interface/switch.workbook",
    "chars": 3825,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: Android\npackages: []\n---\n\n# Android Switches\n\nIn this interactive tutorial, you "
  },
  {
    "path": "android/user-interface/views.workbook",
    "chars": 4400,
    "preview": "```json\n{\"platform\":\"Android\",\"uti\":\"com.xamarin.workbook\"}\n```\n\n# Android View Property Animation\n\nIn this interactive "
  },
  {
    "path": "azure/cogs/emotion.workbook/employees.csx",
    "chars": 10799,
    "preview": "// https://github.com/xamarinhq/app-acquaint/blob/2ca9e83c8344d35288e4ea7868ea6e5795a25e9c/App/Common/Acquaint.Data/Seed"
  },
  {
    "path": "azure/cogs/emotion.workbook/index.workbook",
    "chars": 5409,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- iOS\npackages:\n- id: Newtonsoft.Json\n  version: 8.0.3\n- id: Microsoft.Net.Http"
  },
  {
    "path": "azure/cogs/meta.json",
    "chars": 61,
    "preview": "{\n  \"order\":{\n    \"emotion.workbook\":\"Emotion Service\"\n  }\n}\n"
  },
  {
    "path": "azure/meta.json",
    "chars": 80,
    "preview": "{\n  \"order\":{\n    \"tryazure\":\"Try Azure\",\n    \"cogs\":\"Cognitive Services\"\n  }\n}\n"
  },
  {
    "path": "azure/tryazure/TryAzure-Mac.workbook",
    "chars": 1789,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: MacNet45\npackages:\n- id: Newtonsoft.Json\n  version: 9.0.1\n- id: Microsoft.Net.Ht"
  },
  {
    "path": "azure/tryazure/TryAzure-WPF.workbook",
    "chars": 1782,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: WPF\npackages:\n- id: Microsoft.Bcl\n  version: 1.1.10\n- id: Newtonsoft.Json\n  vers"
  },
  {
    "path": "azure/tryazure/TryAzure-iOS.workbook",
    "chars": 1781,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: iOS\npackages:\n- id: Microsoft.Bcl\n  version: 1.1.10\n- id: Microsoft.Net.Http\n  v"
  },
  {
    "path": "azure/tryazure/meta.json",
    "chars": 166,
    "preview": "{\n  \"order\":{\n    \"TryAzure-iOS.workbook\":\"Try Azure for iOS\",\n    \"TryAzure-Mac.workbook\":\"Try Azure for Mac\",\n    \"Try"
  },
  {
    "path": "charts/meta.json",
    "chars": 65,
    "preview": "{\n  \"order\":{\n    \"oxyplot\":\"OxyPlot\",\n    \"xplot\":\"XPlot\"\n  }\n}\n"
  },
  {
    "path": "charts/oxyplot/OxyPlot.workbook",
    "chars": 3082,
    "preview": "---\nid: ee57cfd4-3bc0-4069-952d-4fa85802fceb\nuti: com.xamarin.workbook\ncopyright: © Copyright 2015, OxyPlot Contributors"
  },
  {
    "path": "charts/oxyplot/meta.json",
    "chars": 70,
    "preview": "{\n  \"order\":{\n    \"OxyPlot.workbook\":\"Get Started with OxyPlot\"\n  }\n}\n"
  },
  {
    "path": "charts/xplot/XPlot.workbook",
    "chars": 1675,
    "preview": "---\nuti: com.xamarin.workbook\nid: 036795c2-a071-4ad5-9375-d0c82482d37d\ntitle: XPlot\nplatforms:\n- Console\npackages:\n- id:"
  },
  {
    "path": "charts/xplot/meta.json",
    "chars": 66,
    "preview": "{\n  \"order\":{\n    \"XPlot.workbook\":\"Get Started with XPlot\"\n  }\n}\n"
  },
  {
    "path": "csharp/async/README.md",
    "chars": 235,
    "preview": "Async-Await Workbook\n=========\n\nA simple `callback` versus `await` demo related to \n[Xamarin's async support overview](h"
  },
  {
    "path": "csharp/async/async-await-wpf.workbook",
    "chars": 1973,
    "preview": "---\nuti: com.xamarin.workbook\nplatform: WPF\npackages: []\n---\n\n\n# Async 101\n\nA quick explanation of why `async-await` cod"
  },
  {
    "path": "csharp/async/async-await.workbook",
    "chars": 1975,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n---\n\n# Async 101\n\nA quick explanation of why `async-await` code is e"
  },
  {
    "path": "csharp/async/meta.json",
    "chars": 115,
    "preview": "{\n  \"order\":{\n    \"async-await.workbook\":\"Async Await\",\n    \"async-await-wpf.workbook\":\"Async Await for WPF\"\n  }\n}\n"
  },
  {
    "path": "csharp/collections/README.md",
    "chars": 111,
    "preview": "Collections: Arrays Workbook\n=========\n\nQuick explanation of how C# arrays work.\n\n\n![](Screenshots/arrays.png)\n"
  },
  {
    "path": "csharp/collections/arrays.workbook",
    "chars": 2660,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- Console\n---\n\n# Collections: Arrays\n\nAn array is a simple data structure:\n\n* i"
  },
  {
    "path": "csharp/collections/meta.json",
    "chars": 51,
    "preview": "{\n  \"order\":{\n    \"arrays.workbook\":\"Arrays\"\n  }\n}\n"
  },
  {
    "path": "csharp/csharp6/README.md",
    "chars": 193,
    "preview": "C# 6 Workbook\n=========\n\nA smattering of C# 6 syntax examples from this\n[C# 6 overview](https://developer.xamarin.com/gu"
  },
  {
    "path": "csharp/csharp6/csharp6.workbook",
    "chars": 4626,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- Console\n---\n\n# Using C# 6\n\nSome examples from Xamarin's [intro to C# 6](https"
  },
  {
    "path": "csharp/csharp6/meta.json",
    "chars": 56,
    "preview": "{\n  \"order\":{\n    \"csharp6.workbook\":\"Using C# 6\"\n  }\n}\n"
  },
  {
    "path": "csharp/csharp7/csharp7.workbook",
    "chars": 30290,
    "preview": "---\nuti: com.xamarin.workbook\ntitle: What's New in C# 7 | C# Guide\nplatforms:\n- Console\n---\n\n> ⚠️ C# 7 is supported in X"
  },
  {
    "path": "csharp/csharp7/index.workbook",
    "chars": 30293,
    "preview": "---\nuti: com.xamarin.workbook\ntitle: What's New in C# 7 | C# Guide\nplatforms:\n- Console\n---\n\n> ⚠️ C# 7 is supported in X"
  },
  {
    "path": "csharp/csharp7/meta.json",
    "chars": 64,
    "preview": "{\n  \"order\":{\n    \"csharp7.workbook\":\"What's new in C# 7\"\n  }\n}\n"
  },
  {
    "path": "csharp/linq/101-linq-examples.workbook/101_Linq_Examples.csx",
    "chars": 41873,
    "preview": "#r \"System.Xml.Linq\"\n#r \"System.Data\"\n#r \"System.Data.DataSetExtensions\"\n\nusing System.Xml.Linq;\nusing System.Data;\n\n\npu"
  },
  {
    "path": "csharp/linq/101-linq-examples.workbook/Customers.xml",
    "chars": 143895,
    "preview": "<?xml version=\"1.0\"?>\r\n<customers>\r\n  <customer>\r\n    <id>ALFKI</id>\r\n    <name>Alfreds Futterkiste</name>\r\n    <addres"
  },
  {
    "path": "csharp/linq/101-linq-examples.workbook/index.workbook",
    "chars": 46582,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- Console\n---\n\n# 101 (and then some) LINQ Examples\n\nLanguage Integrated Query p"
  },
  {
    "path": "csharp/linq/meta.json",
    "chars": 73,
    "preview": "{\n  \"order\":{\n    \"101-linq-examples.workbook\":\"101 Linq Examples\"\n  }\n}\n"
  },
  {
    "path": "csharp/meta.json",
    "chars": 190,
    "preview": "{\n  \"order\":{\n    \"csharp7\":\"C# 7\",\n    \"csharp6\":\"C# 6\",\n    \"async\":\"Async Await\",\n    \"collections\":\"Collections\",\n  "
  },
  {
    "path": "csharp/roslyn/meta.json",
    "chars": 87,
    "preview": "{\n  \"order\":{\n    \"roslyn-syntax-trees.workbook\":\"Exploring Roslyn Syntax Trees\"\n  }\n}\n"
  },
  {
    "path": "csharp/roslyn/roslyn-syntax-trees.workbook/index.workbook",
    "chars": 16756,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- Console\npackages:\n- id: Microsoft.CodeAnalysis.CSharp\n  version: 1.3.2\n---\n\n"
  },
  {
    "path": "graphics/meta.json",
    "chars": 113,
    "preview": "{\n  \"order\":{\n    \"skiasharp\":\"SkiaSharp\",\n    \"urhosharp\":\"UrhoSharp\",\n    \"tiny-renderer\":\"TinyRenderer\"\n  }\n}\n"
  },
  {
    "path": "graphics/skiasharp/colors/colors.workbook/index.workbook",
    "chars": 5434,
    "preview": "---\ntitle: Working with SKColor\nuti: com.xamarin.workbook\nid: a8709e7d-ba63-47a4-8fb3-bed7d3bf9fbb\nplatforms:\n- Console\n"
  },
  {
    "path": "graphics/skiasharp/images/images.workbook/index.workbook",
    "chars": 3586,
    "preview": "---\npackages:\n- id: SkiaSharp\n  version: 1.57.1\nuti: com.xamarin.workbook\nid: 42aced37-cff5-4cd5-8cd7-a23c986406f3\ntitle"
  },
  {
    "path": "graphics/skiasharp/introduction/introduction.workbook/index.workbook",
    "chars": 7557,
    "preview": "---\nid: dd45fdd0-cb47-4fa9-ae05-cb7549704db3\ntitle: Introduction to SkiaSharp\nuti: com.xamarin.workbook\nplatforms:\n- Con"
  },
  {
    "path": "graphics/skiasharp/logo/skialogo-ios.workbook/index.workbook",
    "chars": 9791,
    "preview": "---\nid: 06a9e50c-6510-47e6-9a31-f0c4e2ba9b1a\ntitle: Exploring Drawing with SkiaSharp\nuti: com.xamarin.workbook\nplatforms"
  },
  {
    "path": "graphics/skiasharp/meta.json",
    "chars": 285,
    "preview": "{\n  \"order\":{\n    \"introduction/introduction.workbook\":\"An Introduction\",\n    \"logo/skialogo-ios.workbook\":\"Logo for iOS"
  },
  {
    "path": "graphics/skiasharp/pixmap/pixmap.workbook/index.workbook",
    "chars": 1667,
    "preview": "---\npackages:\n- id: SkiaSharp\n  version: 1.57.1\ntitle: Working with SKPixmap\nuti: com.xamarin.workbook\nid: ab5c4303-8a59"
  },
  {
    "path": "graphics/tiny-renderer/README.md",
    "chars": 320,
    "preview": "# TinyRenderer\n\nThese workbooks are a port of an excellent [C++ series](https://github.com/ssloy/tinyrenderer/wiki) writ"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Listings/ListingTexture.cs",
    "chars": 1476,
    "preview": "using System;\nusing static Renderer.Geometry;\nusing static Renderer.Utils;\n\nnamespace Renderer\n{\n\tstatic class ListingT"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Listings/ListingZBuffer.cs",
    "chars": 1229,
    "preview": "using System;\nusing static Renderer.Geometry;\nusing static Renderer.Utils;\n\nnamespace Renderer\n{\n\tstatic class ListingZ"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Program.cs",
    "chars": 12038,
    "preview": "using System;\nusing static Renderer.Geometry;\nusing static Renderer.Utils;\nusing static Renderer.MatrixHelpers;\n\nnamesp"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Properties/AssemblyInfo.cs",
    "chars": 990,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\n\n// Information about this assembly is defined by the f"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Renderer.csproj",
    "chars": 2616,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microso"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Renderer.sln",
    "chars": 757,
    "preview": "\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 2012\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-0"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Tests/GouraudShaderFixture.cs",
    "chars": 2172,
    "preview": "using System;\nusing NUnit.Framework;\n\nusing static Renderer.Utils;\nusing static Renderer.MatrixHelpers;\nusing static Re"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Tests/MatrixFixture.cs",
    "chars": 308,
    "preview": "using System;\n\nusing NUnit.Framework;\n\nusing static Renderer.MatrixHelpers;\n\nnamespace Renderer\n{\n\t[TestFixture]\n\tpubli"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Tests/ModelFixture.cs",
    "chars": 637,
    "preview": "using System;\n\nusing NUnit.Framework;\n\nnamespace Renderer\n{\n\tstatic class ModelUtils\n\t{\n\t\tconst string text = @\"\nv 0 0 "
  },
  {
    "path": "graphics/tiny-renderer/Renderer/Tests/VectorFixture.cs",
    "chars": 2503,
    "preview": "using System;\n\nusing NUnit.Framework;\n\nnamespace Renderer\n{\n\t[TestFixture]\n\tpublic class VectorFixture\n\t{\n\t\t[Test]\n\t\tpu"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/WorkbookItems/Geometry.cs",
    "chars": 3985,
    "preview": "using System;\n\nnamespace Renderer\n{\n\tstruct Vec2f\n\t{\n\t\tpublic float x;\n\t\tpublic float y;\n\n\t\tpublic float this [int i] {"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/WorkbookItems/Image.cs",
    "chars": 10094,
    "preview": "using System;\n\nnamespace Renderer\n{\n\tusing System.IO;\n\n\tenum Format\n\t{\n\t\tGRAYSCALE = 1,\n\t\tBGR = 3,\n\t\tBGRA = 4\n\t}\n\n\tstru"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/WorkbookItems/Matrix.cs",
    "chars": 11603,
    "preview": "using System;\n\nnamespace Renderer\n{\n\tpublic struct Matrix4\n\t{\n\t\tpublic const int Len = 4;\n\n\t\tpublic float R0C0, R0C1, R"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/WorkbookItems/Model.cs",
    "chars": 2692,
    "preview": "using System;\n\nnamespace Renderer\n{\n\tusing System.Collections.Generic;\n\tusing System.Linq;\n\n\tstruct Face\n\t{\n\t\tpublic in"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/WorkbookItems/Shaders.cs",
    "chars": 16602,
    "preview": "using System;\nusing static Renderer.Geometry;\nusing static Renderer.MatrixHelpers;\nusing static Renderer.ShaderUtils;\n\n"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/WorkbookItems/Utils.cs",
    "chars": 8278,
    "preview": "using System;\n\nusing static Renderer.Geometry;\n\nnamespace Renderer\n{\n\tstatic class Utils\n\t{\n\t\tpublic static Vec3f Baryc"
  },
  {
    "path": "graphics/tiny-renderer/Renderer/packages.config",
    "chars": 127,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"NUnit\" version=\"3.5.0\" targetFramework=\"net45\" />\n</pa"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/Model.csx",
    "chars": 2734,
    "preview": "using System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/index.workbook",
    "chars": 5454,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson1.workbook/obj/african_head.obj",
    "chars": 194973,
    "preview": "v -0.000581696 -0.734665 -0.623267\nv 0.000283538 -1 0.286843\nv -0.117277 -0.973564 0.306907\nv -0.382144 -0.890788 0.2212"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/Model.csx",
    "chars": 2577,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;\n\tpublic int [] Textures;\n\tp"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/index.workbook",
    "chars": 16231,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/lesson1.workbook",
    "chars": 5218,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/lesson2.csx",
    "chars": 1908,
    "preview": "using static Geometry;\n\nvar light_dir = new Vec3f { x = 0, y = 0, z = -1 };\n\nvar world = new Vec3f [3];\nvar screen = new"
  },
  {
    "path": "graphics/tiny-renderer/lesson2.workbook/obj/african_head.obj",
    "chars": 194973,
    "preview": "v -0.000581696 -0.734665 -0.623267\nv 0.000283538 -1 0.286843\nv -0.117277 -0.973564 0.306907\nv -0.382144 -0.890788 0.2212"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/Model.csx",
    "chars": 2577,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;\n\tpublic int [] Textures;\n\tp"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/index.workbook",
    "chars": 12317,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/lesson1.workbook",
    "chars": 5218,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/lesson2.csx",
    "chars": 1908,
    "preview": "using static Geometry;\n\nvar light_dir = new Vec3f { x = 0, y = 0, z = -1 };\n\nvar world = new Vec3f [3];\nvar screen = new"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/lesson2.workbook",
    "chars": 15995,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/lesson3.csx",
    "chars": 2064,
    "preview": "using static Geometry;\n\nvar headTexture = Image.Load (\"obj/african_head_diffuse.tga\");\nheadTexture.VerticalFlip ();\n\nflo"
  },
  {
    "path": "graphics/tiny-renderer/lesson3.workbook/obj/african_head.obj",
    "chars": 194973,
    "preview": "v -0.000581696 -0.734665 -0.623267\nv 0.000283538 -1 0.286843\nv -0.117277 -0.973564 0.306907\nv -0.382144 -0.890788 0.2212"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/Model.csx",
    "chars": 2577,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;\n\tpublic int [] Textures;\n\tp"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/index.workbook",
    "chars": 15981,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson1.workbook",
    "chars": 5218,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson2.csx",
    "chars": 1908,
    "preview": "using static Geometry;\n\nvar light_dir = new Vec3f { x = 0, y = 0, z = -1 };\n\nvar world = new Vec3f [3];\nvar screen = new"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson2.workbook",
    "chars": 15995,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson3.csx",
    "chars": 2064,
    "preview": "using static Geometry;\n\nvar headTexture = Image.Load (\"obj/african_head_diffuse.tga\");\nheadTexture.VerticalFlip ();\n\nflo"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson3.workbook",
    "chars": 12081,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/lesson4.csx",
    "chars": 531,
    "preview": "Vec2f[] uv = new Vec2f [3];\n\nFunc<Image, Vec3f, Vec2f> uvMap = (texture, v) => new Vec2f {\n\tx = v.x * (texture.Width - 1"
  },
  {
    "path": "graphics/tiny-renderer/lesson4.workbook/obj/cube.obj",
    "chars": 369,
    "preview": "v -1 -1  1\nv  1 -1  1\nv  1  0  1\nv  0  1  1\nv -1  1  1\nv  1  1  0\nv -1 -1 -1\nv  1 -1 -1\nv  1  1 -1\nv -1  1 -1\n\nf 1/-1/-1"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/Model.csx",
    "chars": 2577,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;\n\tpublic int [] Textures;\n\tp"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/index.workbook",
    "chars": 9764,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson1.workbook",
    "chars": 5218,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson2.csx",
    "chars": 1908,
    "preview": "using static Geometry;\n\nvar light_dir = new Vec3f { x = 0, y = 0, z = -1 };\n\nvar world = new Vec3f [3];\nvar screen = new"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson2.workbook",
    "chars": 15995,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson3.csx",
    "chars": 2064,
    "preview": "using static Geometry;\n\nvar headTexture = Image.Load (\"obj/african_head_diffuse.tga\");\nheadTexture.VerticalFlip ();\n\nflo"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson3.workbook",
    "chars": 12081,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson4.csx",
    "chars": 531,
    "preview": "Vec2f[] uv = new Vec2f [3];\n\nFunc<Image, Vec3f, Vec2f> uvMap = (texture, v) => new Vec2f {\n\tx = v.x * (texture.Width - 1"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson4.workbook",
    "chars": 15745,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/lesson5.csx",
    "chars": 660,
    "preview": "using static Geometry;\n\nvar eye = new Vec3f { x = 1, y = 1, z = 3 };\nvar center = new Vec3f { x = 0, y = 0, z = 0 };\nvar"
  },
  {
    "path": "graphics/tiny-renderer/lesson5.workbook/obj/african_head.obj",
    "chars": 194973,
    "preview": "v -0.000581696 -0.734665 -0.623267\nv 0.000283538 -1 0.286843\nv -0.117277 -0.973564 0.306907\nv -0.382144 -0.890788 0.2212"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/Model.csx",
    "chars": 2577,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;\n\tpublic int [] Textures;\n\tp"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/index.workbook",
    "chars": 21642,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson1.workbook",
    "chars": 5218,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson2.csx",
    "chars": 1908,
    "preview": "using static Geometry;\n\nvar light_dir = new Vec3f { x = 0, y = 0, z = -1 };\n\nvar world = new Vec3f [3];\nvar screen = new"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson2.workbook",
    "chars": 15995,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson3.csx",
    "chars": 2064,
    "preview": "using static Geometry;\n\nvar headTexture = Image.Load (\"obj/african_head_diffuse.tga\");\nheadTexture.VerticalFlip ();\n\nflo"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson3.workbook",
    "chars": 12081,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson4.csx",
    "chars": 531,
    "preview": "Vec2f[] uv = new Vec2f [3];\n\nFunc<Image, Vec3f, Vec2f> uvMap = (texture, v) => new Vec2f {\n\tx = v.x * (texture.Width - 1"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson4.workbook",
    "chars": 15745,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson5.csx",
    "chars": 660,
    "preview": "using static Geometry;\n\nvar eye = new Vec3f { x = 1, y = 1, z = 3 };\nvar center = new Vec3f { x = 0, y = 0, z = 0 };\nvar"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson5.workbook",
    "chars": 9528,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/lesson6.csx",
    "chars": 5978,
    "preview": "using static Geometry;\nusing static MatrixHelpers;\nusing static ShaderUtils;\n\nvar diabloModel = Model.FromFile (\"obj/dia"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/obj/african_head.obj",
    "chars": 194973,
    "preview": "v -0.000581696 -0.734665 -0.623267\nv 0.000283538 -1 0.286843\nv -0.117277 -0.973564 0.306907\nv -0.382144 -0.890788 0.2212"
  },
  {
    "path": "graphics/tiny-renderer/lesson6.workbook/obj/diablo3_pose.obj",
    "chars": 427302,
    "preview": "v 0.11526 0.700717 0.0677257\nv 0.114223 0.654606 0.0821706\nv 0.119952 0.67202 0.101202\nv 0.12069 0.712368 0.0932415\nv 0."
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/Image.csx",
    "chars": 9756,
    "preview": "using System.IO;\n\nenum Format\n{\n\tGRAYSCALE = 1,\n\tBGR = 3,\n\tBGRA = 4\n}\n\nstruct Color\n{\n\t// the value stored as little end"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/ImageResultHandler.csx",
    "chars": 441,
    "preview": "using XIR = Xamarin.Interactive.Representations;\n\nInteractiveAgent.RepresentationManager.AddProvider<Image> (img => {\n  "
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/LICENSE.txt",
    "chars": 887,
    "preview": "Tiny Renderer, https://github.com/ssloy/tinyrenderer\nCopyright Dmitry V. Sokolov\n\nThis software is provided 'as-is', wit"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/Matrix.csx",
    "chars": 9539,
    "preview": "using System;\n\npublic struct Matrix4\n{\n\tpublic const int Len = 4;\n\n\tpublic float R0C0, R0C1, R0C2, R0C3;\n\tpublic float R"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/Model.csx",
    "chars": 2577,
    "preview": "using System.Collections.Generic;\nusing System.Linq;\n\nstruct Face\n{\n\tpublic int [] Vertices;\n\tpublic int [] Textures;\n\tp"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/WpfImageResultHandler.csx",
    "chars": 860,
    "preview": "using System;\nusing System.IO;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nusing XIR = Xamarin.Inte"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/index.workbook",
    "chars": 13951,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson1.csx",
    "chars": 906,
    "preview": "int width = 800;\nint height = 800;\nvar headModel = Model.FromFile (\"obj/african_head.obj\");\n\nstatic void Swap<T>(ref T x"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson1.workbook",
    "chars": 5218,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson2.csx",
    "chars": 1908,
    "preview": "using static Geometry;\n\nvar light_dir = new Vec3f { x = 0, y = 0, z = -1 };\n\nvar world = new Vec3f [3];\nvar screen = new"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson2.workbook",
    "chars": 15995,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson3.csx",
    "chars": 2064,
    "preview": "using static Geometry;\n\nvar headTexture = Image.Load (\"obj/african_head_diffuse.tga\");\nheadTexture.VerticalFlip ();\n\nflo"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson3.workbook",
    "chars": 12081,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Image.csx\"\n#load \"M"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson4.csx",
    "chars": 531,
    "preview": "Vec2f[] uv = new Vec2f [3];\n\nFunc<Image, Vec3f, Vec2f> uvMap = (texture, v) => new Vec2f {\n\tx = v.x * (texture.Width - 1"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson4.workbook",
    "chars": 15745,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson5.csx",
    "chars": 660,
    "preview": "using static Geometry;\n\nvar eye = new Vec3f { x = 1, y = 1, z = 3 };\nvar center = new Vec3f { x = 0, y = 0, z = 0 };\nvar"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson5.workbook",
    "chars": 9528,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson6.csx",
    "chars": 5978,
    "preview": "using static Geometry;\nusing static MatrixHelpers;\nusing static ShaderUtils;\n\nvar diabloModel = Model.FromFile (\"obj/dia"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson6.workbook",
    "chars": 21407,
    "preview": "---\nuti: com.xamarin.workbook\nplatforms:\n- MacNet45\n- WPF\n---\n\n```csharp\n#load \"Geometry.csx\"\n#load \"Matrix.csx\"\n#load \""
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/lesson6bis.csx",
    "chars": 2513,
    "preview": "using static Geometry;\nusing static MatrixHelpers;\nusing static ShaderUtils;\n\nclass TangentShader : IShader\n{\n    // tri"
  },
  {
    "path": "graphics/tiny-renderer/lesson6bis.workbook/obj/african_head.obj",
    "chars": 194973,
    "preview": "v -0.000581696 -0.734665 -0.623267\nv 0.000283538 -1 0.286843\nv -0.117277 -0.973564 0.306907\nv -0.382144 -0.890788 0.2212"
  },
  {
    "path": "graphics/tiny-renderer/lesson7.workbook/Geometry.csx",
    "chars": 3752,
    "preview": "struct Vec2f\n{\n\tpublic float x;\n\tpublic float y;\n\n\tpublic float this [int i] {\n\t\tget {\n\t\t\tif (i == 0) return x;\n\t\t\tif (i"
  }
]

// ... and 457 more files (download for full content)

About this extraction

This page contains the full source code of the xamarin/Workbooks GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 657 files (4.9 MB), approximately 1.3M tokens, and a symbol index with 206 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!