From 6852ce08370d68ce66ba22aeccd272a7fbd9f723 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:25:33 -0800 Subject: [PATCH 01/32] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 23d79fd3b3..532050f8c2 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ Here is the current list of What The Hack hackathons available in this repositor - [Fabric Real-time Intelligence](/069-FabricRealTimeIntelligence/README.md) - [Cosmic Troubleshooting](/056-CosmicTroubleshooting/README.md) - [Data Governance with Microsoft Purview](/051-MicrosoftPurview/README.md) +- [Data Science In Microsoft Fabric](/072-DataScienceInFabric/README.md) - [SQL Modernization and Migration](/043-SQLModernization/README.md) - [OSS Database Migration](/033-OSSDatabaseMigration/README.md) - [MLOps from Scratch](/032-MLOpsFromScratch/README.md) From d041e02271214da984f71a2602b0fa3869c67ac9 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot <> Date: Fri, 28 Mar 2025 20:59:44 +0000 Subject: [PATCH 02/32] Created WhatTheHack template stub --- .../Coach/Lectures.pptx | Bin 0 -> 196287 bytes xxx-AIWithConfluentOnAzure/Coach/README.md | 79 ++++++++++++++ .../Coach/Solution-00.md | 20 ++++ .../Coach/Solution-01.md | 20 ++++ .../Coach/Solution-02.md | 20 ++++ .../Coach/Solution-03.md | 20 ++++ .../Coach/Solution-04.md | 20 ++++ .../Coach/Solution-05.md | 20 ++++ .../Coach/Solutions/.gitkeep | 0 xxx-AIWithConfluentOnAzure/README.md | 40 +++++++ .../Student/Challenge-00.md | 100 ++++++++++++++++++ .../Student/Challenge-01.md | 99 +++++++++++++++++ .../Student/Challenge-02.md | 99 +++++++++++++++++ .../Student/Challenge-03.md | 99 +++++++++++++++++ .../Student/Challenge-04.md | 99 +++++++++++++++++ .../Student/Challenge-05.md | 99 +++++++++++++++++ .../Student/Resources/.gitkeep | 0 17 files changed, 834 insertions(+) create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Lectures.pptx create mode 100644 xxx-AIWithConfluentOnAzure/Coach/README.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-00.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-01.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-02.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-03.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-04.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-05.md create mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep create mode 100644 xxx-AIWithConfluentOnAzure/README.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-00.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-01.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-02.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-03.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-04.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-05.md create mode 100644 xxx-AIWithConfluentOnAzure/Student/Resources/.gitkeep diff --git a/xxx-AIWithConfluentOnAzure/Coach/Lectures.pptx b/xxx-AIWithConfluentOnAzure/Coach/Lectures.pptx new file mode 100644 index 0000000000000000000000000000000000000000..34cfe52f45a056e33791ebf176cee017e41362e0 GIT binary patch literal 196287 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�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%0A2O;OS!shB_ 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 J40sEG@;^hlltKUi literal 0 HcmV?d00001 diff --git a/xxx-AIWithConfluentOnAzure/Coach/README.md b/xxx-AIWithConfluentOnAzure/Coach/README.md new file mode 100644 index 0000000000..aa8938734d --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/README.md @@ -0,0 +1,79 @@ +# What The Hack - AIWithConfluentOnAzure - Coach Guide + +## Introduction + +Welcome to the coach's guide for the AIWithConfluentOnAzure What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. + +This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. + +**NOTE:** If you are a Hackathon participant, this is the answer guide. Don't cheat yourself by looking at these during the hack! Go learn something. :) + +## Coach's Guides + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** + - Prepare your workstation to work with Azure. +- Challenge 01: **[Title of Challenge](./Solution-01.md)** + - Description of challenge +- Challenge 02: **[Title of Challenge](./Solution-02.md)** + - Description of challenge +- Challenge 03: **[Title of Challenge](./Solution-03.md)** + - Description of challenge +- Challenge 04: **[Title of Challenge](./Solution-04.md)** + - Description of challenge +- Challenge 05: **[Title of Challenge](./Solution-05.md)** + - Description of challenge + +## Coach Prerequisites + +This hack has pre-reqs that a coach is responsible for understanding and/or setting up BEFORE hosting an event. Please review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for information on how to host a hack event. + +The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. + +### Student Resources + +Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. + +Always refer students to the [What The Hack website](https://aka.ms/wth) for the student guide: [https://aka.ms/wth](https://aka.ms/wth) + +**NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. + +### Additional Coach Prerequisites (Optional) + +_Please list any additional pre-event setup steps a coach would be required to set up such as, creating or hosting a shared dataset, or deploying a lab environment._ + +## Azure Requirements + +This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. + +_Please list Azure subscription requirements._ + +_For example:_ + +- Azure resources that will be consumed by a student implementing the hack's challenges +- Azure permissions required by a student to complete the hack's challenges. + +## Suggested Hack Agenda (Optional) + +_This section is optional. You may wish to provide an estimate of how long each challenge should take for an average squad of students to complete and/or a proposal of how many challenges a coach should structure each session for a multi-session hack event. For example:_ + +- Sample Day 1 + - Challenge 1 (1 hour) + - Challenge 2 (30 mins) + - Challenge 3 (2 hours) +- Sample Day 2 + - Challenge 4 (45 mins) + - Challenge 5 (1 hour) + - Challenge 6 (45 mins) + +## Repository Contents + +_The default files & folders are listed below. You may add to this if you want to specify what is in additional sub-folders you may add._ + +- `./Coach` + - Coach's Guide and related files +- `./Coach/Solutions` + - Solution files with completed example answers to a challenge +- `./Student` + - Student's Challenge Guide +- `./Student/Resources` + - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-00.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-00.md new file mode 100644 index 0000000000..8ca1a44d71 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/Solution-00.md @@ -0,0 +1,20 @@ +# Challenge 00 - - Coach's Guide + +**[Home](./README.md)** - [Next Solution >](./Solution-01.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-01.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-01.md new file mode 100644 index 0000000000..01d1e30c27 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/Solution-01.md @@ -0,0 +1,20 @@ +# Challenge 01 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-02.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-02.md new file mode 100644 index 0000000000..1ef8ca5035 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/Solution-02.md @@ -0,0 +1,20 @@ +# Challenge 02 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-03.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-03.md new file mode 100644 index 0000000000..9591196509 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/Solution-03.md @@ -0,0 +1,20 @@ +# Challenge 03 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-04.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-04.md new file mode 100644 index 0000000000..90a770fdb3 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/Solution-04.md @@ -0,0 +1,20 @@ +# Challenge 04 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-05.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-05.md new file mode 100644 index 0000000000..c320bf9745 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Coach/Solution-05.md @@ -0,0 +1,20 @@ +# Challenge 05 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-04.md) - **[Home](./README.md)** + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep b/xxx-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xxx-AIWithConfluentOnAzure/README.md b/xxx-AIWithConfluentOnAzure/README.md new file mode 100644 index 0000000000..55be3a34d8 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/README.md @@ -0,0 +1,40 @@ +# What The Hack - AIWithConfluentOnAzure + +## Introduction + +The IoT Hack of the Century will take you on a whirlwind tour in the world of IoT and how it is being used in the modern world of mineral extraction in exotic locations like the Arctic and the wilds of South Africa. + +## Learning Objectives + +In this hack you will be solving the common business problem that companies in the mineral extraction industry face and how IoT solutions from Azure are brought to bare + +1. Provision an IoT Hub +2. Set up an IoT Edge device +3. Bring Azure Sphere to your solution for scale and resiliency + +## Challenges + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** + - Prepare your workstation to work with Azure. +- Challenge 01: **[Title of Challenge](Student/Challenge-01.md)** + - Description of challenge +- Challenge 02: **[Title of Challenge](Student/Challenge-02.md)** + - Description of challenge +- Challenge 03: **[Title of Challenge](Student/Challenge-03.md)** + - Description of challenge +- Challenge 04: **[Title of Challenge](Student/Challenge-04.md)** + - Description of challenge +- Challenge 05: **[Title of Challenge](Student/Challenge-05.md)** + - Description of challenge + +## Prerequisites + +- Your own Azure subscription with Owner access +- Visual Studio Code +- Azure CLI +- An AVNET X231 device + +## Contributors + +- Jane Q. Public +- Joe T. Muppet diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-00.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-00.md new file mode 100644 index 0000000000..61aa89aa4b --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -0,0 +1,100 @@ +# Challenge 00 - Prerequisites - Ready, Set, GO! + +**[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) + +**_This is a template for "Challenge Zero" which focuses on getting prerequisites set up for the hack. The italicized text provides hints & examples of what should or should NOT go in each section._** + +**_We have included links to some common What The Hack pre-reqs in this template. All common prerequisite links go to the WTH-CommonPrerequisites page where there are more details on what each tool's purpose is._** + +**_You should remove any common pre-reqs that are not required for your hack. Then add additional pre-reqs that are required for your hack in the Description section below._** + +**_You should remove all italicized & sample text in this template and replace with your content._** + +## Introduction + +Thank you for participating in the AIWithConfluentOnAzure What The Hack. Before you can hack, you will need to set up some prerequisites. + +## Common Prerequisites + +We have compiled a list of common tools and software that will come in handy to complete most What The Hack Azure-based hacks! + +You might not need all of them for the hack you are participating in. However, if you work with Azure on a regular basis, these are all things you should consider having in your toolbox. + +<!-- If you are editing this template manually, be aware that these links are only designed to work if this Markdown file is in the /xxx-HackName/Student/ folder of your hack. --> + +- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) +- [Windows Subsystem for Linux](../../000-HowToHack/WTH-Common-Prerequisites.md#windows-subsystem-for-linux) +- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) + - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) + - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) + - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) + - [Azure PowerShell CmdLets](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-powershell-cmdlets) + - [Azure Cloud Shell](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cloud-shell) +- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) + - [VS Code plugin for ARM Templates](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code-plugins-for-arm-templates) +- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) + +## Description + +_This section should clearly state any additional prerequisite tools that need to be installed or set up in the Azure environment that the student will hack in._ + +_While ordered lists are generally not welcome in What The Hack challenge descriptions, you can use one here in Challenge Zero IF and only IF the steps you are asking the student to perform are not core to the learning objectives of the hack._ + +_For example, if the hack is on IoT Devices and you want the student to deploy an ARM/Bicep template that sets up the environment they will hack in without them needing to understand how ARM/Bicep templates work, you can provide step-by-step instructions on how to deploy the ARM/Bicep template._ + +_Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack. You should leave the sample text below in that refers to the Resources.zip file._ + +**\*NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resources.zip file provided by the coach.\* + +**\*NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.\* + +_Sample challenge zero text for the IoT Hack Of The Century:_ + +Now that you have the common pre-requisites installed on your workstation, there are prerequisites specifc to this hack. + +Your coach will provide you with a Resources.zip file that contains resources you will need to complete the hack. If you plan to work locally, you should unpack it on your workstation. If you plan to use the Azure Cloud Shell, you should upload it to the Cloud Shell and unpack it there. + +Please install these additional tools: + +- [Azure IoT Tools](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools) extension for Visual Studio Code +- .NET SDK 6.0 or later installed on your development machine. This can be downloaded from [here](https://www.microsoft.com/net/download/all) for multiple platforms. + +In the `/Challenge00/` folder of the Resources.zip file, you will find an ARM template, `setupIoTEnvironment.json` that sets up the initial hack environment in Azure you will work with in subsequent challenges. + +Please deploy the template by running the following Azure CLI commands from the location of the template file: +``` +az group create --name myIoT-rg --location eastus +az group deployment create -g myIoT-rg --name HackEnvironment -f setupIoTEnvironment.json +``` + +## Success Criteria + +_Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach._ + +_The success criteria should not be a list of instructions._ + +_Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."_ + +_Sample success criteria for the IoT prerequisites challenge:_ + +To complete this challenge successfully, you should be able to: + +- Verify that you have a bash shell with the Azure CLI available. +- Verify that the ARM template has deployed the following resources in Azure: + - Azure IoT Hub + - Virtual Network + - Jumpbox VM + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +_Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario._ + +**\*Note:** Use descriptive text for each link instead of just URLs.\* + +_Sample IoT resource links:_ + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md new file mode 100644 index 0000000000..fcf81ed831 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -0,0 +1,99 @@ +# Challenge 01 - <Title of Challenge> + +[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md new file mode 100644 index 0000000000..459fb175d5 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -0,0 +1,99 @@ +# Challenge 02 - <Title of Challenge> + +[< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md new file mode 100644 index 0000000000..88656873ba --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -0,0 +1,99 @@ +# Challenge 03 - <Title of Challenge> + +[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md new file mode 100644 index 0000000000..a032304040 --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -0,0 +1,99 @@ +# Challenge 04 - <Title of Challenge> + +[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md new file mode 100644 index 0000000000..027fffe5bf --- /dev/null +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md @@ -0,0 +1,99 @@ +# Challenge 05 - <Title of Challenge> + +[< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** + +***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** + +## Pre-requisites (Optional) + +*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* + +## Introduction + +*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* + +*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* + +*For example:* + +When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. + +## Description + +*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* + +***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* + +***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* + +*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* + +***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* + +***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* + +***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* + +*Sample challenge text for the IoT Hack Of The Century:* + +In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. + +You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. + +Please configure the thingamajig with the following specifications: +- Use dynamic IP addresses +- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" +- Deny access to "IoTProxyShip" + +You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). + +## Success Criteria + +*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* + +*The success criteria should not be a list of instructions.* + +*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* + +*Sample success criteria for the IoT sample challenge:* + +To complete this challenge successfully, you should be able to: +- Verify that the IoT device boots properly after its thingamajig is configured. +- Verify that the thingamajig can connect to the mothership. +- Demonstrate that the thingamajic will not connect to the IoTProxyShip + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Resources/.gitkeep b/xxx-AIWithConfluentOnAzure/Student/Resources/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 From 029078acae8980ee0cb402f45ed638185898f7d9 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 28 Mar 2025 16:32:59 -0700 Subject: [PATCH 03/32] Update README.md Update challenge names --- xxx-AIWithConfluentOnAzure/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/README.md b/xxx-AIWithConfluentOnAzure/README.md index 55be3a34d8..c0a2800b1c 100644 --- a/xxx-AIWithConfluentOnAzure/README.md +++ b/xxx-AIWithConfluentOnAzure/README.md @@ -1,4 +1,4 @@ -# What The Hack - AIWithConfluentOnAzure +# What The Hack - AI With Confluent On Azure ## Introduction @@ -16,15 +16,15 @@ In this hack you will be solving the common business problem that companies in t - Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** - Prepare your workstation to work with Azure. -- Challenge 01: **[Title of Challenge](Student/Challenge-01.md)** +- Challenge 01: **[Configuration of Agentic Resources and Deployment of Backend](Student/Challenge-01.md)** - Description of challenge -- Challenge 02: **[Title of Challenge](Student/Challenge-02.md)** +- Challenge 02: **[Configuration of Chat Interface and Frontend](Student/Challenge-02.md)** - Description of challenge -- Challenge 03: **[Title of Challenge](Student/Challenge-03.md)** +- Challenge 03: **[Simulation of Employee - Reports, Status etc](Student/Challenge-03.md)** - Description of challenge -- Challenge 04: **[Title of Challenge](Student/Challenge-04.md)** +- Challenge 04: **[Simulation of Suppliers - Replenishments](Student/Challenge-04.md)** - Description of challenge -- Challenge 05: **[Title of Challenge](Student/Challenge-05.md)** +- Challenge 05: **[Simulation of Customers - Purchases and Returns](Student/Challenge-05.md)** - Description of challenge ## Prerequisites From 4903ed770e236ea811d916bba91ba6510bdd852c Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 28 Mar 2025 16:50:59 -0700 Subject: [PATCH 04/32] Update README.md --- xxx-AIWithConfluentOnAzure/README.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/README.md b/xxx-AIWithConfluentOnAzure/README.md index c0a2800b1c..f693803823 100644 --- a/xxx-AIWithConfluentOnAzure/README.md +++ b/xxx-AIWithConfluentOnAzure/README.md @@ -2,15 +2,20 @@ ## Introduction -The IoT Hack of the Century will take you on a whirlwind tour in the world of IoT and how it is being used in the modern world of mineral extraction in exotic locations like the Arctic and the wilds of South Africa. +This hackathon immerses you in building a real-time AI agent using **Confluent Cloud on Microsoft Azure**. You’ll learn how Confluent’s data streaming platform—based on Apache Kafka—can connect and process retail data in real time, enabling AI-driven insights that keep pace with constantly changing business conditions [1][2]. Whether it’s ingesting product SKUs or synchronizing inventory levels, Confluent Cloud on Azure offers a unified, scalable, and secure platform to design near real-time pipelines and deliver accurate, intelligent solutions. + +Throughout this hack, you’ll capture data from diverse sources—such as transaction logs, returns, and purchase records—and then transform or enrich that data using Apache Flink or ksqlDB. The result is an always up-to-date data backbone, ready to power AI-driven applications that swiftly respond to customer needs, supplier demands, and dynamic inventory scenarios [3][4]. + ## Learning Objectives -In this hack you will be solving the common business problem that companies in the mineral extraction industry face and how IoT solutions from Azure are brought to bare +By completing this hack, you will: -1. Provision an IoT Hub -2. Set up an IoT Edge device -3. Bring Azure Sphere to your solution for scale and resiliency +- **Set up a real-time streaming environment** on Confluent Cloud in Azure, incorporating best practices for scalability, reliability, and security. +- **Ingest and process diverse data sources** using Apache Kafka, exploring how pre-built Confluent connectors facilitate end-to-end data pipelines. +- **Apply basic stream processing** through ksqlDB or Apache Flink to merge, filter, or aggregate event data in real time. +- **Sync transformed data to Azure services** like Cosmos DB or Azure AI Search, ensuring your AI agent always has a near real-time view of retail operations. +- **Lay the groundwork for AI-driven decision-making**, demonstrating how real-time data improves accuracy and responsiveness for both customers and internal stakeholders. ## Challenges @@ -32,9 +37,15 @@ In this hack you will be solving the common business problem that companies in t - Your own Azure subscription with Owner access - Visual Studio Code - Azure CLI -- An AVNET X231 device + +## References +- 1 https://www.confluent.io/apache-kafka-vs-confluent/ +- 2 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/overview +- 3 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create +- 4 https://www.confluent.io/hub/ ## Contributors -- Jane Q. Public -- Joe T. Muppet +- Andy Huang +- Israel Ekpo +- Juan Llovet de Casso From 0c97896126956f09024e36ae9ac37a190a139546 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 30 May 2025 16:52:53 -0700 Subject: [PATCH 05/32] Update Challenge-01.md --- .../Student/Challenge-01.md | 55 ++----------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md index fcf81ed831..65ccfa2826 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -1,66 +1,21 @@ -# Challenge 01 - <Title of Challenge> +# Challenge 01 - Configuration of Agentic Resources and Deployment of Backend [< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** - -## Pre-requisites (Optional) - -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* - ## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* - -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* - -*For example:* - -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. +In this challenge, you'll focus on deploying the backend API that will serve as the foundation for your real-time AI agent. This API will eventually consume data streamed through Confluent Cloud on Azure and surface intelligent responses based on the latest available information. ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* - -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* - -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* - -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* +*Need to Update once we confirm architecture* -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* - -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* - -*Sample challenge text for the IoT Hack Of The Century:* - -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. - -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. - -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" - -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). ## Success Criteria -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* - -*The success criteria should not be a list of instructions.* - -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* - -*Sample success criteria for the IoT sample challenge:* - To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +- Show that your Azure resources and API have been deployed +- Verify that the API is reachable and responsive. ## Learning Resources From 9366c8b3b71221938994ae57872e60806fae99b7 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 30 May 2025 16:56:10 -0700 Subject: [PATCH 06/32] Update Challenge-02.md --- .../Student/Challenge-02.md | 49 ++----------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md index 459fb175d5..95b09b6c8f 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -1,62 +1,23 @@ -# Challenge 02 - <Title of Challenge> +# Challenge 02 - Configuration of Chat Interface and Frontend [< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** -## Pre-requisites (Optional) +## Pre-requisites -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +You must complete **Challenge 01** before starting this challenge. The backend API must be successfully deployed and reachable, as the frontend will depend on it for communication and functionality. ## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +In this challenge, you'll configure and deploy the frontend user interface that interacts with your backend API. This frontend UI will allow users to send and receive messages to the AI agent powered by real-time streaming data from Confluent Cloud. **Need to update as I am just filling in generic verbiage** -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* - -*For example:* - -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* - -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* - -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* - -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* - -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* - -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* - -*Sample challenge text for the IoT Hack Of The Century:* - -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. - -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. - -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" - -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +**Need to Update as we get details of infrastructure. ## Success Criteria -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* - -*The success criteria should not be a list of instructions.* - -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* - -*Sample success criteria for the IoT sample challenge:* - To complete this challenge successfully, you should be able to: - Verify that the IoT device boots properly after its thingamajig is configured. - Verify that the thingamajig can connect to the mothership. From 21523c3082f91cb17f4b97639ce7ec42a91ca6c8 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 30 May 2025 16:56:52 -0700 Subject: [PATCH 07/32] Update Challenge-02.md --- xxx-AIWithConfluentOnAzure/Student/Challenge-02.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md index 95b09b6c8f..6a5379954e 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -19,9 +19,8 @@ In this challenge, you'll configure and deploy the frontend user interface that ## Success Criteria To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +- Show that your frontend and related Azure resources have been deployed. +- Verify that the frontend can communicate with the backend API and receive a valid response. ## Learning Resources From bb4a5c15b4a22b78dcf3660fc0d9379f96236d59 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 30 May 2025 17:00:43 -0700 Subject: [PATCH 08/32] Update Challenge-03.md --- .../Student/Challenge-03.md | 67 +++++++------------ 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md index 88656873ba..d906dd20e0 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -1,66 +1,49 @@ -# Challenge 03 - <Title of Challenge> +# Challenge 03 - Simulation of Employee Persona [< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** -## Pre-requisites (Optional) +## Pre-requisites -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend interface must be fully deployed and functional, as this challenge builds on top of the running application infrastructure. -## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +## Introduction -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +In this challenge, you'll simulate the experience of an employee interacting with the AI agent to perform various business-critical operations. This persona has access to operational data such as purchases, returns, and inventory, and can also perform updates to the product catalog in near real time. -*For example:* +The goal of this challenge is to observe how changes initiated through the agent are processed and reflected across systems in near real time using Confluent Cloud on Azure. These updates—whether querying data or modifying records—flow through Kafka topics, are processed via stream processors like Flink or ksqlDB, and are reflected in the destination datastore with minimal delay. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* - -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* - -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* - -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* - -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +In this challenge, you will authenticate as an employee and issue commands to the AI agent to retrieve and update retail operations data. These interactions are routed through the backend API, processed via Confluent Cloud's real-time data infrastructure, and ultimately reflected in the destination datastore. -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +Please implement the following capabilities for the employee persona: -*Sample challenge text for the IoT Hack Of The Century:* +- Authenticate using an employee ID and 4-digit PIN. +- Retrieve summaries for a specific date: + - Total purchases + - Total replenishments + - Total returns + - Net sales (purchases - returns) +- Query current inventory level of a specific SKU. +- Modify inventory-related data: + - Change the maximum inventory level of a specific SKU. + - Update the unit price of a specific SKU. + - Add a new SKU to the product catalog. + - Modify the list of SKUs a vendor is authorized to replenish. -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. +All modifications should propagate through Confluent Cloud and be reflected in the destination data store (e.g., Cosmos DB or Azure AI Search) in near real time. -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. - -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" - -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). ## Success Criteria -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* - -*The success criteria should not be a list of instructions.* - -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* - -*Sample success criteria for the IoT sample challenge:* - To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +- Show that employee users can authenticate using ID and PIN. +- Show at least three successful read operations. +- Show at least two successful write operations. +- Verify that data changes propagate through Confluent Cloud and are reflected in the destination data store in near real time. ## Learning Resources From f9d21809bc2f50311608be974258f565f1df3b81 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 30 May 2025 17:03:39 -0700 Subject: [PATCH 09/32] Update Challenge-04.md --- .../Student/Challenge-04.md | 62 ++++++------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md index a032304040..bf4057afc2 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -1,66 +1,42 @@ -# Challenge 04 - <Title of Challenge> +# Challenge 04 - Simulation of Suppliers - Replenishments [< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** -## Pre-requisites (Optional) +## Pre-requisites -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend, frontend, and employee data operations must be functional to ensure supplier-related workflows integrate with the rest of the system. -## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +## Introduction -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +In this challenge, you’ll take on the role of a vendor or supplier interacting with the AI agent to monitor and replenish inventory levels. These interactions are authorized and scoped to SKUs each vendor is allowed to manage. -*For example:* +The goal of this challenge is to observe how inventory replenishment operations are processed in near real time through Confluent Cloud on Azure and reflected immediately in downstream systems like Cosmos DB or Azure AI Search. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* - -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* - -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* - -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* - -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +Vendors will authenticate into the system using their vendor ID and 4-digit PIN. Once authenticated, the vendor will use the AI agent to retrieve SKU-level data and issue replenishment commands. -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +Please implement the following capabilities for the vendor persona: -*Sample challenge text for the IoT Hack Of The Century:* +- Authenticate using vendor ID and 4-digit PIN. +- Retrieve: + - A list of SKUs the vendor is authorized to replenish. + - The Maximum Inventory Level (MIL) for each of those SKUs. + - The current inventory level of a specific authorized SKU. +- Replenish the inventory of an authorized SKU up to 100% of its MIL. -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. - -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. - -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" - -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +All replenishment updates should be routed through Confluent Cloud and reflected in the destination data store in near real time. ## Success Criteria -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* - -*The success criteria should not be a list of instructions.* - -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* - -*Sample success criteria for the IoT sample challenge:* - To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +- Show that vendor users can authenticate using ID and PIN. +- Verify that you are able to retrie a authorized SKUs and their inventory information. +- Verify a successful replenishment operation that updates inventory to the correct MIL occurs. +- Verify that inventory updates are reflected in the destination data store in near real time through Confluent Cloud. ## Learning Resources From 93039f45ef17cbe9b76a9ce99e73a4702984ef2d Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 30 May 2025 17:06:14 -0700 Subject: [PATCH 10/32] Update Challenge-05.md --- .../Student/Challenge-05.md | 65 +++++++------------ 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md index 027fffe5bf..84588aeb18 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md @@ -1,66 +1,47 @@ -# Challenge 05 - <Title of Challenge> +# Challenge 05 - Simulation of Customers - Purchases and Returns [< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** -***This is a template for a single challenge. The italicized text provides hints & examples of what should or should NOT go in each section. You should remove all italicized & sample text and replace with your content.*** ## Pre-requisites (Optional) -*Your hack's "Challenge 0" should cover pre-requisites for the entire hack, and thus this section is optional and may be omitted. If you wish to spell out specific previous challenges that must be completed before starting this challenge, you may do so here.* +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend chat interface must be fully deployed and functional for customer interactions to work correctly. -## Introduction -*This section should provide an overview of the technologies or tasks that will be needed to complete the this challenge. This includes the technical context for the challenge, as well as any new "lessons" the attendees should learn before completing the challenge.* +## Introduction -*Optionally, the coach or event host is encouraged to present a mini-lesson (with a PPT or video) to set up the context & introduction to each challenge. A summary of the content of that mini-lesson is a good candidate for this Introduction section* +In this challenge, you'll simulate how customers interact with the AI agent to browse products, make purchases, and request returns. These interactions represent real-world commerce flows and depend on accurate, up-to-date inventory and pricing information. -*For example:* +The goal of this challenge is to observe how customer-facing operations impact the backend in real time. All updates made through the agent—such as purchasing or returning SKUs—should flow through Confluent Cloud and be reflected in the destination datastore in near real time. -When setting up an IoT device, it is important to understand how 'thingamajigs' work. Thingamajigs are a key part of every IoT device and ensure they are able to communicate properly with edge servers. Thingamajigs require IP addresses to be assigned to them by a server and thus must have unique MAC addresses. In this challenge, you will get hands on with a thingamajig and learn how one is configured. ## Description -*This section should clearly state the goals of the challenge and any high-level instructions you want the students to follow. You may provide a list of specifications required to meet the goals. If this is more than 2-3 paragraphs, it is likely you are not doing it right.* - -***NOTE:** Do NOT use ordered lists as that is an indicator of 'step-by-step' instructions. Instead, use bullet lists to list out goals and/or specifications.* - -***NOTE:** You may use Markdown sub-headers to organize key sections of your challenge description.* - -*Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack.* - -***NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resource.zip file provided by the coach.* - -***NOTE:** As an exception, you may provide a GitHub 'raw' link to an individual file such as a PDF or Office document, so long as it does not open the contents of the file in the What The Hack repo on the GitHub website.* +Customers authenticate using a customer ID and 4-digit PIN. Once signed in, they should be able to browse available SKUs, check stock status, make purchases, and return eligible items. -***NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.* +Please implement the following capabilities for the customer persona: -*Sample challenge text for the IoT Hack Of The Century:* +- Authenticate using customer ID and 4-digit PIN. +- Retrieve: + - A list of all SKUs available in the store, regardless of inventory. + - A list of SKUs currently in stock. + - A list of SKUs currently out of stock. + - The status of a specific SKU, including unit price, inventory level, and discount (if any). +- Add an SKU to the shopping cart (up to available inventory). +- Make a purchase for all items in the cart, generating a receipt ID. +- Retrieve transaction details for a specific receipt ID. +- Return an SKU from a previous purchase by providing a receipt ID, as long as the return is within 14 days of the purchase date. -In this challenge, you will properly configure the thingamajig for your IoT device so that it can communicate with the mother ship. - -You can find a sample `thingamajig.config` file in the `/ChallengeXX` folder of the Resources.zip file provided by your coach. This is a good starting reference, but you will need to discover how to set exact settings. - -Please configure the thingamajig with the following specifications: -- Use dynamic IP addresses -- Only trust the following whitelisted servers: "mothership", "IoTQueenBee" -- Deny access to "IoTProxyShip" - -You can view an architectural diagram of an IoT thingamajig here: [Thingamajig.PDF](/Student/Resources/Architecture.PDF?raw=true). +All purchase and return actions should be processed via Confluent Cloud and reflected in the destination datastore in near real time. ## Success Criteria -*Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach.* - -*The success criteria should not be a list of instructions.* - -*Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."* - -*Sample success criteria for the IoT sample challenge:* - To complete this challenge successfully, you should be able to: -- Verify that the IoT device boots properly after its thingamajig is configured. -- Verify that the thingamajig can connect to the mothership. -- Demonstrate that the thingamajic will not connect to the IoTProxyShip +- Show that customer users can authenticate using ID and PIN. +- Verify you can retrie the product catalog and inventory information. +- Complete a purchase flow with a generated receipt ID. +- Show how you can return a purchased item within the allowed return window. +- Verify that purchases and returns are reflected in the destination data store in near real time through Confluent Cloud. ## Learning Resources From 01011b592127540b9b8fea2ac90ca5f85088ebea Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:14:40 -0700 Subject: [PATCH 11/32] Update Challenge-04.md --- xxx-AIWithConfluentOnAzure/Student/Challenge-04.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md index bf4057afc2..f225b41ef7 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -19,8 +19,6 @@ The goal of this challenge is to observe how inventory replenishment operations Vendors will authenticate into the system using their vendor ID and 4-digit PIN. Once authenticated, the vendor will use the AI agent to retrieve SKU-level data and issue replenishment commands. -Please implement the following capabilities for the vendor persona: - - Authenticate using vendor ID and 4-digit PIN. - Retrieve: - A list of SKUs the vendor is authorized to replenish. From 266d0395d584c305d09c1f95f380347c7fee7acb Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:14:55 -0700 Subject: [PATCH 12/32] Update Challenge-05.md --- xxx-AIWithConfluentOnAzure/Student/Challenge-05.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md index 84588aeb18..86387ad878 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md @@ -19,8 +19,6 @@ The goal of this challenge is to observe how customer-facing operations impact t Customers authenticate using a customer ID and 4-digit PIN. Once signed in, they should be able to browse available SKUs, check stock status, make purchases, and return eligible items. -Please implement the following capabilities for the customer persona: - - Authenticate using customer ID and 4-digit PIN. - Retrieve: - A list of all SKUs available in the store, regardless of inventory. From 16c8d48754b5156e3165b531486a98c9aff27a9a Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:15:08 -0700 Subject: [PATCH 13/32] Update Challenge-03.md --- xxx-AIWithConfluentOnAzure/Student/Challenge-03.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md index d906dd20e0..539e22e5a1 100644 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md +++ b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -19,8 +19,6 @@ The goal of this challenge is to observe how changes initiated through the agent In this challenge, you will authenticate as an employee and issue commands to the AI agent to retrieve and update retail operations data. These interactions are routed through the backend API, processed via Confluent Cloud's real-time data infrastructure, and ultimately reflected in the destination datastore. -Please implement the following capabilities for the employee persona: - - Authenticate using an employee ID and 4-digit PIN. - Retrieve summaries for a specific date: - Total purchases From 6a9b6bb4732208be9a4254272ab98245e0278dac Mon Sep 17 00:00:00 2001 From: Israel Ekpo <isekpo@microsoft.com> Date: Fri, 17 Oct 2025 14:46:58 -0400 Subject: [PATCH 14/32] saving changes --- .../devcontainer.json | 33 +++++++++++++++++++ .gitignore | 33 ++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/073-AIWithConfluentOnAzure/devcontainer.json diff --git a/.devcontainer/073-AIWithConfluentOnAzure/devcontainer.json b/.devcontainer/073-AIWithConfluentOnAzure/devcontainer.json new file mode 100644 index 0000000000..04ae874375 --- /dev/null +++ b/.devcontainer/073-AIWithConfluentOnAzure/devcontainer.json @@ -0,0 +1,33 @@ +{ + "image": "mcr.microsoft.com/devcontainers/python:3.12-bookworm", + "workspaceFolder": "/workspace/073-AIWithConfluentOnAzure/Student/Resources", + "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", + "hostRequirements": { + "cpus": 2, + "memory": "4gb" + }, + "waitFor": "onCreateCommand", + "updateContentCommand": "python3 -m pip install -r requirements.txt", + "postCreateCommand": "", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/azure-cli:1": {}, + "ghcr.io/devcontainers/features/terraform:1": {} + }, + "customizations": { + "codespaces": { + "openFiles": [] + }, + "vscode": { + "extensions": [ + "ms-toolsai.jupyter", + "ms-python.python", + "github.copilot", + "github.copilot-chat", + "HashiCorp.terraform", + "humao.rest-client", + "ms-azuretools.vscode-docker" + ] + } + } + } diff --git a/.gitignore b/.gitignore index c2fd5482d4..dac96335f9 100644 --- a/.gitignore +++ b/.gitignore @@ -333,4 +333,35 @@ ASALocalRun/ .mfractor/ .DS_Store -.env \ No newline at end of file +.env + + +shared_environment_variables.sh +shared_environment_variables.env + +.env.sh + +# Confluent Ignores +*confluent-environment* +*confluent-environment.sh + +# Terraform Stuff +terraform.tfstate.backup +.terraform +*.tfstate +.terraform* +azure_environment_variables.sh +main_variables.tf +microsoft_hackathon.plan + +# Othe files from Python and Node +.cosmos_permissions +DRAFT.txt +node_modules +.idea +.vscode +.project +__pycache__ +*.final.json + + From e0376f5e84e5154d76d01cd7d01582dbe3a1a700 Mon Sep 17 00:00:00 2001 From: Israel Ekpo <isekpo@microsoft.com> Date: Fri, 17 Oct 2025 14:47:52 -0400 Subject: [PATCH 15/32] saving changes --- .../Coach/Lectures.pptx | Bin 0 -> 196287 bytes 073-AIWithConfluentOnAzure/Coach/README.md | 79 + .../Coach/Solution-00.md | 20 + .../Coach/Solution-01.md | 20 + .../Coach/Solution-02.md | 20 + .../Coach/Solution-03.md | 20 + .../Coach/Solution-04.md | 20 + .../Coach/Solution-05.md | 20 + .../Coach/Solutions/.gitkeep | 0 .../Coach/Solutions/flink-sql/README.md | 33 + .../Solutions/flink-sql/data_pipeline-ddl.sql | 50 + .../Solutions/flink-sql/data_pipeline-dml.sql | 97 + .../Solutions/flink-sql/ddl-sink-tables.sql | 0 .../Solutions/flink-sql/ddl-source-tables.sql | 18 + .../flink-sql/drafts/departments.sql | 19 + .../flink-sql/drafts/departments_flat.sql | 4 + .../flink-sql/drafts/flat_tables.sql | 109 + .../flink-sql/drafts/product_skus.sql | 10 + .../Solutions/flink-sql/drafts/purchases.sql | 36 + .../flink-sql/drafts/replenishments.sql | 29 + .../flink-sql/drafts/retail_tables.sql | 125 + .../Solutions/flink-sql/drafts/returns.sql | 32 + .../check_resources_status.sh | 71 + .../maintenance_scripts/environment-azure.sh | 7 + .../environment-confluent.sh | 8 + .../fix_azure_blob_store.sh | 12 + .../fix_azure_cosmos_db.sh | 10 + 073-AIWithConfluentOnAzure/README.md | 51 + .../Student/Challenge-00.md | 100 + .../Student/Challenge-01.md | 54 + .../Student/Challenge-02.md | 59 + .../Student/Challenge-03.md | 80 + .../Student/Challenge-04.md | 73 + .../Student/Challenge-05.md | 78 + .../Student/Resources/.gitkeep | 0 .../agentic-application/.dockerignore | 7 + .../agentic-application/.env.sh.example | 50 + .../agentic-application/DOCKER_BUILDS.md | 82 + .../agentic-application/Dockerfile.base | 15 + .../agentic-application/Dockerfile.customer | 16 + .../agentic-application/Dockerfile.employee | 17 + .../agentic-application/Dockerfile.inventory | 18 + .../Dockerfile.replenishment | 18 + .../agentic-application/Dockerfile.shopping | 18 + .../agentic-application/Dockerfile.supplier | 16 + .../Resources/agentic-application/LICENSE | 21 + .../Resources/agentic-application/NOTES.md | 85 + .../Resources/agentic-application/README.md | 3 + .../RUNNING_THE_APPLICATION.md | 142 ++ .../agent_customer_experience.py | 33 + .../agent_employee_experience.py | 68 + .../agent_supplier_experience.py | 74 + .../contoso_retail_application/__init__.py | 45 + .../agent_graphs.py | 200 ++ .../ai_foundry_setup.py | 9 + .../data_access_objects.py | 568 +++++ .../contoso_retail_application/models.py | 228 ++ .../service_configuration_inventory.py | 97 + .../service_configuration_replenishment.py | 79 + .../service_configuration_shopping.py | 13 + .../static_dataset.py | 35 + .../contoso_retail_application/utils.py | 9 + .../entrypoints/entrypoint.agent-customer.sh | 23 + .../entrypoints/entrypoint.agent-employee.sh | 23 + .../entrypoints/entrypoint.agent-supplier.sh | 23 + .../entrypoints/entrypoint.mcp-inventory.sh | 25 + .../entrypoint.mcp-replenishment.sh | 25 + .../entrypoints/entrypoint.mcp-shopping.sh | 25 + .../Resources/agentic-application/main.py | 3 + .../agentic-application/mcp_service.py | 56 + .../agentic-application/pyproject.toml | 13 + .../tests/test_replenishment.py | 11 + .../agentic-application/tests/test_sales.py | 11 + .../Resources/agentic-application/uv.lock | 2259 +++++++++++++++++ .../ai-search-schemas/departments_flat.json | 51 + .../ai-search-schemas/net_sales.json | 75 + .../ai-search-schemas/product_inventory.json | 99 + .../Resources/azure-setup-create-indices.sh | 88 + .../Resources/compose/docker-compose.yml | 34 + .../shared_environment_variables.env.example | 32 + .../Student/Resources/confluent-setup-cli.sh | 19 + .../confluent-setup-create-connectors.sh | 44 + .../confluent-setup-create-topics.sh | 95 + .../confluent-setup-delete-connectors.sh | 73 + .../confluent-setup-delete-schemas.sh | 42 + .../confluent-setup-delete-topics.sh | 49 + .../Resources/confluent-setup-flink-sql.sh | 0 ...fluent-setup-populate-connector-configs.sh | 47 + ...onfluent-setup-populate-connector-reset.sh | 31 + .../ai_search_departments_flat.example.json | 36 + .../ai_search_net_sales.example.json | 36 + .../ai_search_product_inventory.example.json | 36 + .../azure_blob_departments.example.json | 35 + .../azure_blob_product_pricing.example.json | 35 + .../azure_blob_product_skus.example.json | 35 + .../cosmos_db_purchases.example.json | 27 + .../cosmos_db_replenishments.example.json | 27 + .../cosmos_db_returns.example.json | 27 + .../Student/Resources/retail_store/README.md | 11 + .../UPLOADING_BLOB_STORE_CONTENTS.md | 19 + .../retail_store/azure_blob_upload.sh | 38 + .../retail_store/departments/appliance.json | 4 + .../retail_store/departments/cleaning.json | 4 + .../retail_store/departments/dairy.json | 4 + .../retail_store/departments/deli.json | 4 + .../retail_store/departments/meat.json | 4 + .../retail_store/departments/pharmacy.json | 4 + .../retail_store/departments/produce.json | 4 + .../schemas/departments-key.schema | 6 + .../schemas/departments-value.schema | 16 + .../retail_store/departments/seafood.json | 4 + .../departments_flat/appliance.json | 4 + .../departments_flat/cleaning.json | 4 + .../retail_store/departments_flat/dairy.json | 4 + .../retail_store/departments_flat/deli.json | 4 + .../retail_store/departments_flat/meat.json | 4 + .../departments_flat/pharmacy.json | 4 + .../departments_flat/produce.json | 4 + .../schemas/departments_flat-key.schema | 6 + .../schemas/departments_flat-value.schema | 16 + .../departments_flat/seafood.json | 4 + .../Resources/retail_store/net_sales/101.json | 6 + .../net_sales/schemas/net_sales-key.schema | 6 + .../net_sales/schemas/net_sales-value.schema | 25 + .../retail_store/product_inventory/101.json | 8 + .../retail_store/product_inventory/102.json | 8 + .../schemas/product_inventory-key.schema | 6 + .../schemas/product_inventory-value.schema | 37 + .../retail_store/product_pricing/101.json | 5 + .../retail_store/product_pricing/102.json | 5 + .../retail_store/product_pricing/103.json | 5 + .../retail_store/product_pricing/104.json | 5 + .../retail_store/product_pricing/105.json | 5 + .../retail_store/product_pricing/106.json | 5 + .../retail_store/product_pricing/107.json | 5 + .../retail_store/product_pricing/108.json | 5 + .../retail_store/product_pricing/109.json | 5 + .../retail_store/product_pricing/110.json | 5 + .../retail_store/product_pricing/111.json | 5 + .../retail_store/product_pricing/112.json | 5 + .../retail_store/product_pricing/113.json | 5 + .../retail_store/product_pricing/114.json | 5 + .../retail_store/product_pricing/115.json | 5 + .../retail_store/product_pricing/116.json | 5 + .../retail_store/product_pricing/117.json | 5 + .../retail_store/product_pricing/118.json | 5 + .../retail_store/product_pricing/119.json | 5 + .../retail_store/product_pricing/120.json | 5 + .../retail_store/product_pricing/121.json | 5 + .../retail_store/product_pricing/122.json | 5 + .../retail_store/product_pricing/123.json | 5 + .../retail_store/product_pricing/124.json | 5 + .../retail_store/product_pricing/125.json | 5 + .../retail_store/product_pricing/201.json | 5 + .../retail_store/product_pricing/202.json | 5 + .../retail_store/product_pricing/203.json | 5 + .../retail_store/product_pricing/204.json | 5 + .../retail_store/product_pricing/205.json | 5 + .../retail_store/product_pricing/206.json | 5 + .../retail_store/product_pricing/207.json | 5 + .../retail_store/product_pricing/208.json | 5 + .../retail_store/product_pricing/209.json | 5 + .../retail_store/product_pricing/210.json | 5 + .../retail_store/product_pricing/211.json | 5 + .../retail_store/product_pricing/212.json | 5 + .../retail_store/product_pricing/213.json | 5 + .../retail_store/product_pricing/214.json | 5 + .../retail_store/product_pricing/215.json | 5 + .../retail_store/product_pricing/216.json | 5 + .../retail_store/product_pricing/217.json | 5 + .../retail_store/product_pricing/218.json | 5 + .../retail_store/product_pricing/219.json | 5 + .../retail_store/product_pricing/220.json | 5 + .../retail_store/product_pricing/221.json | 5 + .../retail_store/product_pricing/222.json | 5 + .../retail_store/product_pricing/223.json | 5 + .../retail_store/product_pricing/224.json | 5 + .../retail_store/product_pricing/225.json | 5 + .../retail_store/product_pricing/301.json | 5 + .../retail_store/product_pricing/302.json | 5 + .../retail_store/product_pricing/303.json | 5 + .../retail_store/product_pricing/304.json | 5 + .../retail_store/product_pricing/305.json | 5 + .../retail_store/product_pricing/306.json | 5 + .../retail_store/product_pricing/307.json | 5 + .../retail_store/product_pricing/308.json | 5 + .../retail_store/product_pricing/309.json | 5 + .../retail_store/product_pricing/310.json | 5 + .../retail_store/product_pricing/311.json | 5 + .../retail_store/product_pricing/312.json | 5 + .../retail_store/product_pricing/313.json | 5 + .../retail_store/product_pricing/314.json | 5 + .../retail_store/product_pricing/315.json | 5 + .../retail_store/product_pricing/316.json | 5 + .../retail_store/product_pricing/317.json | 5 + .../retail_store/product_pricing/318.json | 5 + .../retail_store/product_pricing/319.json | 5 + .../retail_store/product_pricing/320.json | 5 + .../retail_store/product_pricing/321.json | 5 + .../retail_store/product_pricing/322.json | 5 + .../retail_store/product_pricing/323.json | 5 + .../retail_store/product_pricing/324.json | 5 + .../retail_store/product_pricing/325.json | 5 + .../retail_store/product_pricing/401.json | 5 + .../retail_store/product_pricing/402.json | 5 + .../retail_store/product_pricing/403.json | 5 + .../retail_store/product_pricing/404.json | 5 + .../retail_store/product_pricing/405.json | 5 + .../retail_store/product_pricing/406.json | 5 + .../retail_store/product_pricing/407.json | 5 + .../retail_store/product_pricing/408.json | 5 + .../retail_store/product_pricing/409.json | 5 + .../retail_store/product_pricing/410.json | 5 + .../retail_store/product_pricing/411.json | 5 + .../retail_store/product_pricing/412.json | 5 + .../retail_store/product_pricing/413.json | 5 + .../retail_store/product_pricing/414.json | 5 + .../retail_store/product_pricing/415.json | 5 + .../retail_store/product_pricing/416.json | 5 + .../retail_store/product_pricing/417.json | 5 + .../retail_store/product_pricing/418.json | 5 + .../retail_store/product_pricing/419.json | 5 + .../retail_store/product_pricing/420.json | 5 + .../retail_store/product_pricing/421.json | 5 + .../retail_store/product_pricing/422.json | 5 + .../retail_store/product_pricing/423.json | 5 + .../retail_store/product_pricing/424.json | 5 + .../retail_store/product_pricing/425.json | 5 + .../retail_store/product_pricing/501.json | 5 + .../retail_store/product_pricing/502.json | 5 + .../retail_store/product_pricing/503.json | 5 + .../retail_store/product_pricing/504.json | 5 + .../retail_store/product_pricing/505.json | 5 + .../retail_store/product_pricing/506.json | 5 + .../retail_store/product_pricing/507.json | 5 + .../retail_store/product_pricing/508.json | 5 + .../retail_store/product_pricing/509.json | 5 + .../retail_store/product_pricing/510.json | 5 + .../retail_store/product_pricing/511.json | 5 + .../retail_store/product_pricing/512.json | 5 + .../retail_store/product_pricing/513.json | 5 + .../retail_store/product_pricing/514.json | 5 + .../retail_store/product_pricing/515.json | 5 + .../retail_store/product_pricing/516.json | 5 + .../retail_store/product_pricing/517.json | 5 + .../retail_store/product_pricing/518.json | 5 + .../retail_store/product_pricing/519.json | 5 + .../retail_store/product_pricing/520.json | 5 + .../retail_store/product_pricing/521.json | 5 + .../retail_store/product_pricing/522.json | 5 + .../retail_store/product_pricing/523.json | 5 + .../retail_store/product_pricing/524.json | 5 + .../retail_store/product_pricing/525.json | 5 + .../retail_store/product_pricing/601.json | 5 + .../retail_store/product_pricing/602.json | 5 + .../retail_store/product_pricing/603.json | 5 + .../retail_store/product_pricing/604.json | 5 + .../retail_store/product_pricing/605.json | 5 + .../retail_store/product_pricing/606.json | 5 + .../retail_store/product_pricing/607.json | 5 + .../retail_store/product_pricing/608.json | 5 + .../retail_store/product_pricing/609.json | 5 + .../retail_store/product_pricing/610.json | 5 + .../retail_store/product_pricing/611.json | 5 + .../retail_store/product_pricing/612.json | 5 + .../retail_store/product_pricing/613.json | 5 + .../retail_store/product_pricing/614.json | 5 + .../retail_store/product_pricing/615.json | 5 + .../retail_store/product_pricing/616.json | 5 + .../retail_store/product_pricing/617.json | 5 + .../retail_store/product_pricing/618.json | 5 + .../retail_store/product_pricing/619.json | 5 + .../retail_store/product_pricing/620.json | 5 + .../retail_store/product_pricing/621.json | 5 + .../retail_store/product_pricing/622.json | 5 + .../retail_store/product_pricing/623.json | 5 + .../retail_store/product_pricing/624.json | 5 + .../retail_store/product_pricing/625.json | 5 + .../retail_store/product_pricing/701.json | 5 + .../retail_store/product_pricing/702.json | 5 + .../retail_store/product_pricing/703.json | 5 + .../retail_store/product_pricing/704.json | 5 + .../retail_store/product_pricing/705.json | 5 + .../retail_store/product_pricing/706.json | 5 + .../retail_store/product_pricing/707.json | 5 + .../retail_store/product_pricing/708.json | 5 + .../retail_store/product_pricing/709.json | 5 + .../retail_store/product_pricing/710.json | 5 + .../retail_store/product_pricing/711.json | 5 + .../retail_store/product_pricing/712.json | 5 + .../retail_store/product_pricing/713.json | 5 + .../retail_store/product_pricing/714.json | 5 + .../retail_store/product_pricing/715.json | 5 + .../retail_store/product_pricing/716.json | 5 + .../retail_store/product_pricing/717.json | 5 + .../retail_store/product_pricing/718.json | 5 + .../retail_store/product_pricing/719.json | 5 + .../retail_store/product_pricing/720.json | 5 + .../retail_store/product_pricing/721.json | 5 + .../retail_store/product_pricing/722.json | 5 + .../retail_store/product_pricing/723.json | 5 + .../retail_store/product_pricing/724.json | 5 + .../retail_store/product_pricing/725.json | 5 + .../retail_store/product_pricing/801.json | 5 + .../retail_store/product_pricing/802.json | 5 + .../retail_store/product_pricing/803.json | 5 + .../retail_store/product_pricing/804.json | 5 + .../retail_store/product_pricing/805.json | 5 + .../retail_store/product_pricing/806.json | 5 + .../retail_store/product_pricing/807.json | 5 + .../retail_store/product_pricing/808.json | 5 + .../retail_store/product_pricing/809.json | 5 + .../retail_store/product_pricing/810.json | 5 + .../retail_store/product_pricing/811.json | 5 + .../retail_store/product_pricing/812.json | 5 + .../retail_store/product_pricing/813.json | 5 + .../retail_store/product_pricing/814.json | 5 + .../retail_store/product_pricing/815.json | 5 + .../retail_store/product_pricing/816.json | 5 + .../retail_store/product_pricing/817.json | 5 + .../retail_store/product_pricing/818.json | 5 + .../retail_store/product_pricing/819.json | 5 + .../retail_store/product_pricing/820.json | 5 + .../retail_store/product_pricing/821.json | 5 + .../retail_store/product_pricing/822.json | 5 + .../retail_store/product_pricing/823.json | 5 + .../retail_store/product_pricing/824.json | 5 + .../retail_store/product_pricing/825.json | 5 + .../schemas/product_pricing-key.schema | 7 + .../schemas/product_pricing-value.schema | 19 + .../retail_store/product_skus/101.json | 7 + .../retail_store/product_skus/102.json | 7 + .../retail_store/product_skus/103.json | 7 + .../retail_store/product_skus/104.json | 7 + .../retail_store/product_skus/105.json | 7 + .../retail_store/product_skus/106.json | 7 + .../retail_store/product_skus/107.json | 7 + .../retail_store/product_skus/108.json | 7 + .../retail_store/product_skus/109.json | 7 + .../retail_store/product_skus/110.json | 7 + .../retail_store/product_skus/111.json | 7 + .../retail_store/product_skus/112.json | 7 + .../retail_store/product_skus/113.json | 7 + .../retail_store/product_skus/114.json | 7 + .../retail_store/product_skus/115.json | 7 + .../retail_store/product_skus/116.json | 7 + .../retail_store/product_skus/117.json | 7 + .../retail_store/product_skus/118.json | 7 + .../retail_store/product_skus/119.json | 7 + .../retail_store/product_skus/120.json | 7 + .../retail_store/product_skus/121.json | 7 + .../retail_store/product_skus/122.json | 7 + .../retail_store/product_skus/123.json | 7 + .../retail_store/product_skus/124.json | 7 + .../retail_store/product_skus/125.json | 7 + .../retail_store/product_skus/201.json | 7 + .../retail_store/product_skus/202.json | 7 + .../retail_store/product_skus/203.json | 7 + .../retail_store/product_skus/204.json | 7 + .../retail_store/product_skus/205.json | 7 + .../retail_store/product_skus/206.json | 7 + .../retail_store/product_skus/207.json | 7 + .../retail_store/product_skus/208.json | 7 + .../retail_store/product_skus/209.json | 7 + .../retail_store/product_skus/210.json | 7 + .../retail_store/product_skus/211.json | 7 + .../retail_store/product_skus/212.json | 7 + .../retail_store/product_skus/213.json | 7 + .../retail_store/product_skus/214.json | 7 + .../retail_store/product_skus/215.json | 7 + .../retail_store/product_skus/216.json | 7 + .../retail_store/product_skus/217.json | 7 + .../retail_store/product_skus/218.json | 7 + .../retail_store/product_skus/219.json | 7 + .../retail_store/product_skus/220.json | 7 + .../retail_store/product_skus/221.json | 7 + .../retail_store/product_skus/222.json | 7 + .../retail_store/product_skus/223.json | 7 + .../retail_store/product_skus/224.json | 7 + .../retail_store/product_skus/225.json | 7 + .../retail_store/product_skus/301.json | 7 + .../retail_store/product_skus/302.json | 7 + .../retail_store/product_skus/303.json | 7 + .../retail_store/product_skus/304.json | 7 + .../retail_store/product_skus/305.json | 7 + .../retail_store/product_skus/306.json | 7 + .../retail_store/product_skus/307.json | 7 + .../retail_store/product_skus/308.json | 7 + .../retail_store/product_skus/309.json | 7 + .../retail_store/product_skus/310.json | 7 + .../retail_store/product_skus/311.json | 7 + .../retail_store/product_skus/312.json | 7 + .../retail_store/product_skus/313.json | 7 + .../retail_store/product_skus/314.json | 7 + .../retail_store/product_skus/315.json | 7 + .../retail_store/product_skus/316.json | 7 + .../retail_store/product_skus/317.json | 7 + .../retail_store/product_skus/318.json | 7 + .../retail_store/product_skus/319.json | 7 + .../retail_store/product_skus/320.json | 7 + .../retail_store/product_skus/321.json | 7 + .../retail_store/product_skus/322.json | 7 + .../retail_store/product_skus/323.json | 7 + .../retail_store/product_skus/324.json | 7 + .../retail_store/product_skus/325.json | 7 + .../retail_store/product_skus/401.json | 7 + .../retail_store/product_skus/402.json | 7 + .../retail_store/product_skus/403.json | 7 + .../retail_store/product_skus/404.json | 7 + .../retail_store/product_skus/405.json | 7 + .../retail_store/product_skus/406.json | 7 + .../retail_store/product_skus/407.json | 7 + .../retail_store/product_skus/408.json | 7 + .../retail_store/product_skus/409.json | 7 + .../retail_store/product_skus/410.json | 7 + .../retail_store/product_skus/411.json | 7 + .../retail_store/product_skus/412.json | 7 + .../retail_store/product_skus/413.json | 7 + .../retail_store/product_skus/414.json | 7 + .../retail_store/product_skus/415.json | 7 + .../retail_store/product_skus/416.json | 7 + .../retail_store/product_skus/417.json | 7 + .../retail_store/product_skus/418.json | 7 + .../retail_store/product_skus/419.json | 7 + .../retail_store/product_skus/420.json | 7 + .../retail_store/product_skus/421.json | 7 + .../retail_store/product_skus/422.json | 7 + .../retail_store/product_skus/423.json | 7 + .../retail_store/product_skus/424.json | 7 + .../retail_store/product_skus/425.json | 7 + .../retail_store/product_skus/501.json | 7 + .../retail_store/product_skus/502.json | 7 + .../retail_store/product_skus/503.json | 7 + .../retail_store/product_skus/504.json | 7 + .../retail_store/product_skus/505.json | 7 + .../retail_store/product_skus/506.json | 7 + .../retail_store/product_skus/507.json | 7 + .../retail_store/product_skus/508.json | 7 + .../retail_store/product_skus/509.json | 7 + .../retail_store/product_skus/510.json | 7 + .../retail_store/product_skus/511.json | 7 + .../retail_store/product_skus/512.json | 7 + .../retail_store/product_skus/513.json | 7 + .../retail_store/product_skus/514.json | 7 + .../retail_store/product_skus/515.json | 7 + .../retail_store/product_skus/516.json | 7 + .../retail_store/product_skus/517.json | 7 + .../retail_store/product_skus/518.json | 7 + .../retail_store/product_skus/519.json | 7 + .../retail_store/product_skus/520.json | 7 + .../retail_store/product_skus/521.json | 7 + .../retail_store/product_skus/522.json | 7 + .../retail_store/product_skus/523.json | 7 + .../retail_store/product_skus/524.json | 7 + .../retail_store/product_skus/525.json | 7 + .../retail_store/product_skus/601.json | 7 + .../retail_store/product_skus/602.json | 7 + .../retail_store/product_skus/603.json | 7 + .../retail_store/product_skus/604.json | 7 + .../retail_store/product_skus/605.json | 7 + .../retail_store/product_skus/606.json | 7 + .../retail_store/product_skus/607.json | 7 + .../retail_store/product_skus/608.json | 7 + .../retail_store/product_skus/609.json | 7 + .../retail_store/product_skus/610.json | 7 + .../retail_store/product_skus/611.json | 7 + .../retail_store/product_skus/612.json | 7 + .../retail_store/product_skus/613.json | 7 + .../retail_store/product_skus/614.json | 7 + .../retail_store/product_skus/615.json | 7 + .../retail_store/product_skus/616.json | 7 + .../retail_store/product_skus/617.json | 7 + .../retail_store/product_skus/618.json | 7 + .../retail_store/product_skus/619.json | 7 + .../retail_store/product_skus/620.json | 7 + .../retail_store/product_skus/621.json | 7 + .../retail_store/product_skus/622.json | 7 + .../retail_store/product_skus/623.json | 7 + .../retail_store/product_skus/624.json | 7 + .../retail_store/product_skus/625.json | 7 + .../retail_store/product_skus/701.json | 7 + .../retail_store/product_skus/702.json | 7 + .../retail_store/product_skus/703.json | 7 + .../retail_store/product_skus/704.json | 7 + .../retail_store/product_skus/705.json | 7 + .../retail_store/product_skus/706.json | 7 + .../retail_store/product_skus/707.json | 7 + .../retail_store/product_skus/708.json | 7 + .../retail_store/product_skus/709.json | 7 + .../retail_store/product_skus/710.json | 7 + .../retail_store/product_skus/711.json | 7 + .../retail_store/product_skus/712.json | 7 + .../retail_store/product_skus/713.json | 7 + .../retail_store/product_skus/714.json | 7 + .../retail_store/product_skus/715.json | 7 + .../retail_store/product_skus/716.json | 7 + .../retail_store/product_skus/717.json | 7 + .../retail_store/product_skus/718.json | 7 + .../retail_store/product_skus/719.json | 7 + .../retail_store/product_skus/720.json | 7 + .../retail_store/product_skus/721.json | 7 + .../retail_store/product_skus/722.json | 7 + .../retail_store/product_skus/723.json | 7 + .../retail_store/product_skus/724.json | 7 + .../retail_store/product_skus/725.json | 7 + .../retail_store/product_skus/801.json | 7 + .../retail_store/product_skus/802.json | 7 + .../retail_store/product_skus/803.json | 7 + .../retail_store/product_skus/804.json | 7 + .../retail_store/product_skus/805.json | 7 + .../retail_store/product_skus/806.json | 7 + .../retail_store/product_skus/807.json | 7 + .../retail_store/product_skus/808.json | 7 + .../retail_store/product_skus/809.json | 7 + .../retail_store/product_skus/810.json | 7 + .../retail_store/product_skus/811.json | 7 + .../retail_store/product_skus/812.json | 7 + .../retail_store/product_skus/813.json | 7 + .../retail_store/product_skus/814.json | 7 + .../retail_store/product_skus/815.json | 7 + .../retail_store/product_skus/816.json | 7 + .../retail_store/product_skus/817.json | 7 + .../retail_store/product_skus/818.json | 7 + .../retail_store/product_skus/819.json | 7 + .../retail_store/product_skus/820.json | 7 + .../retail_store/product_skus/821.json | 7 + .../retail_store/product_skus/822.json | 7 + .../retail_store/product_skus/823.json | 7 + .../retail_store/product_skus/824.json | 7 + .../retail_store/product_skus/825.json | 7 + .../schemas/product_skus-key.schema | 6 + .../schemas/product_skus-value.schema | 24 + .../retail_store/purchases/1000.json | 9 + .../retail_store/purchases/1001.json | 9 + .../retail_store/purchases/1002.json | 9 + .../purchases/schemas/purchases-key.schema | 6 + .../purchases/schemas/purchases-value.schema | 63 + .../schemas/purchases_flat-key.schema | 5 + .../schemas/purchases_flat-value.schema | 45 + .../retail_store/replenishments/3000.json | 8 + .../schemas/replenishments-key.schema | 6 + .../schemas/replenishments-value.schema | 65 + .../schemas/replenishments_flat-key.schema | 5 + .../schemas/replenishments_flat-value.schema | 35 + .../Resources/retail_store/returns/2000.json | 12 + .../returns/schemas/returns-key.schema | 6 + .../returns/schemas/returns-value.schema | 66 + .../schemas/returns_flat-key.schema | 5 + .../schemas/returns_flat-value.schema | 41 + .../Student/Resources/terraform/DEPLOY.md | 126 + .../Resources/terraform/api_key_check.sh | 11 + .../Resources/terraform/generate_env_file.sh | 42 + .../Student/Resources/terraform/main.tf | 148 ++ .../Student/Resources/terraform/main_azure.tf | 167 ++ .../Resources/terraform/main_confluent.tf | 264 ++ .../Resources/terraform/main_outputs.tf | 67 + .../Resources/terraform/terraform_cleanup.sh | 13 + 557 files changed, 10861 insertions(+) create mode 100644 073-AIWithConfluentOnAzure/Coach/Lectures.pptx create mode 100644 073-AIWithConfluentOnAzure/Coach/README.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-00.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-01.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-02.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-03.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-04.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-05.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql create mode 100644 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql create mode 100755 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh create mode 100755 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh create mode 100755 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh create mode 100755 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh create mode 100755 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh create mode 100644 073-AIWithConfluentOnAzure/README.md create mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-00.md create mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-01.md create mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-02.md create mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-03.md create mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-04.md create mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-05.md create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/.gitkeep create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf create mode 100644 073-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf create mode 100755 073-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh diff --git a/073-AIWithConfluentOnAzure/Coach/Lectures.pptx b/073-AIWithConfluentOnAzure/Coach/Lectures.pptx new file mode 100644 index 0000000000000000000000000000000000000000..34cfe52f45a056e33791ebf176cee017e41362e0 GIT binary patch literal 196287 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�_IWyNZZ9mNx0@56UmNEa+jb*vV<xCX}_D@Tf6 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%0A2O;OS!shB_ z?k<7lhyv-4=aT>W%#sW5OA=dy+A>)`##P7~ad#4Z4#8~c`RNS1n9;@ZhYqn-l8$5? zw{Ru#2EU}|@!6W%c`*Le<BL89IV_|Z;g8_d>AN6yp&wQJh<{I{13Qqf?uNB2bX59< z6y#TW%jQ}q29eV&n%q}QW(w5*5}Jsw$J!L~U3A>P<_PJ_gophFuc<Q^%sm??MD-pz zN^XR7?s7iVC7@Vty>U~cI$Yw$N;~~Vi-aGO%SAsq5tugJ6`q_R<Dtk+W>K{NWUnz` z`>uN*BQQu(0%KYH`-DF7^1Redr9dluFA{K4Hg{B6`c_pE9rpF|a=O{ExcUv^wMDD( zv)M`|gzmdNgII@gTd7xK<D<->EQ+caL<^tnE0wNsyr`m)@GT)Z46TUCdmsXjq;^v2 z$ylNyF`e0qmB^p{*zmo?9HfqKmaQdNJwG01lI#-gx{)k9miJ82SQ*gilYQkxUHL#m z)1<ekb;od9w?Vc)Gv*%h6g23wA=fS3(ng@Feq!PDca<G7@S#YyCuX`5(c(^KKR?4n z6eV%Hz|xir7g-Sf(rigRrT66ZaP2TB|7dLKW30F2AQGa$IbPg5!i=XduA5Vo991re z!Ew9zDY^25#}(u&$Nl24lKHB@Lifd$3MuwW<h(qcZZk^<&lzzMLTIXXxH3e-z2iOd zv%q=PABu=8m~=EX?wu+1S&ssJKaZqC`eh`2YSlDQ6MFU^oTpD%=8_PSD>a<1h>0uN z76f;U|33>^TNc`~vzZp69;2+Jm}Kt))17xyg3H|NywAM+JN4!);9Axc&YbnG-U&zN z2x$tK=_I2yPlPkcNPTNNx(y}~Khjb9{#`mWeJ3N}>0Z7-c6r<qDYs>+VDv5T-i>pd z9#8snf2}F!A#r4KbGQp^L}Aq+c7N>7r}?eK9Q_E^du~fFl7@E5Jd8x7q5U5%(R+?% ziB)er5Jk*_Z0<N${&~n=fnA2@x35cqm_;zL>ZIlm6{DMk^E0?~tHtSj&C73=)RGJ% ze|b$zGLmIR8(bL$r?^I}@Yg<vvLL$tiStU;zf&vRF^r!3z-UY)wpDrGP#@~5d2sP= zA;Z5ocd1w#>Hc6F=}ld)@{a7|=0F6?x3Lr<3~4B}NPEwp;Bb+f)v2;*3F^YOXgn=* zAFb8au%7FO)_T!Jf&RHy>IZ)mIL>kDkgs1Xv+9Z_9O76CcEBSG1;qDP5943>Vx_ps z(rAA=tf0d#xN+T2kP<OQ-c9?2hDARrwAd5!(Z`CvN!C1FIty+?$#*F4QCXIY_?&sL znBt~4H0wQaS^o0=QOFY>dju^0!?I#39@W1g^~9@jQ*b@&jiY7WM*Ui8RHj7VaZKQg zs<>+qYhe%@^Mp<~_s?l<#!=<!lt+wDv~Gx&^A=p!#bJE|=f|?wwFwJ?zo@5DTn2yO z;z0~+we^RMh6dJHmPy6|a6+NVkFZp00#<D#u)qRA5w`TH&pk+4tuAwM0kk6?|J7Jx zUL+T1k(k_eX3x@fAcY6(q&Y!B-^xIZuxSn2tE+MgV)3WbA|q|+>6hv&nnmg1R(fYF zs7!8Ov#2o2hnIa|XspS-g3R=nf{uk-I*br9hUVXp>1mH|LWEk<J%gas<)bDaZarkc z^92oidlUOZEaiTIYL<y^YtlB{V$9w6<8MQ$nYA;^f5G5s&4!tbNDwRC2ortl*X*&- z#t#>Xhvd2f57nqTRepRas?yZw2rmv#?`>cr`a%qZTXk4;ePF20x;I)#L<-s$U0E|Z z_KsNb9~d#{ksSVmc(M}SszT*GJQi)71jEm#cj$+<tosc<M3gNH`h;3bZt4*_;cF~y zJypUa;zpi8H*!rnW&Q<&8DUH-YaLi#WsYxVv$34j=j}So+LmAFU}BFX|0bZ#9Z1=& z)q=?0F3-BipihpXa$^4!wI-JSf+}_8uJi+%F$F}<jYtQU-tX^bd$vlEl8X`jYpd)* zT0i;MrIhF3+~O^S@VhHp^SPWXg&8`JNhp}u<dCRSgpyi)PplAz6cq1F*iRvA0ru^m zsJFwKzc?tm|MiTuQb&|QY@zXDkNJ_Bn0tv_dH%7j`RbgiXzf_J-d97X>d58gY6Tih zNi+&AOd>8MTTIiWd{f$Aq+l0;Q*-^RB8i(aPe6j1I7{>)VqC4C)Z$g59z7OwFEzq0 zy>0FXS)xW2w^DV|VdK1P%b#L!*sf%OZ)8?zA)_x=lB@Mb<%i|+K)xK{mxdx-3qUPn z+@RJ#;gqSrmc&oabri;Wk(ps0r;wo01j&vr`kY$IM!)|3$jXEUoTj%{1Eb2-BvAO2 z)#H6Lw*pE>{vCBDx#kRMUZ+w2qfMn=%4t89?-R?emurSUH3F<H6$@u`n~ME@>`0_9 zQIcqJNhw_hbpIWG%$SlY_ZI_E!pZoboXzRbB1882`;5zpQQA{v?@O=gGyAsxJ$?bU zYL=ldcfLjS#=`dn?@fvHcFNRIH`D~&dwz(x8;<pa52$@O<LDoW`Jh<dGswADs1T6y z_!w~h^5NzBWPiAZ`$o*N<FVSXyA{#Ba{wqk4So%X#Bh^WYp?7zvD}Rya>slitI=G2 zXRar%{#1>2=%h%dT_dLvP-HPtK<6YyD>pojT)P>V|Go5DVyQ(m3JXjk4j_u;{85(@ zh%kT-;MMAC)VbkpOuBEM?L&@mjZHLA4e#cD=V0#Syzf^pqsvi0?SjLd3ScRdYj*-z z3-&?!lv0inft<b}39dzNM!m%RWr?qsVznN7=SdM)L4sb!M)!7lT;8~wh_C4DX1dQ4 z<Ys8(09N(C&r^3*3vu8&!4nqHjEU!3u#f!<W+-dzXEb!|FHWGqvRN90+07ok@1q4R zf5}mwr$yux6@DHzrP;?Y_nqQO<>&GFuSM-^DB=MC%CFB6yuMfouEYoc2Diu_{^+0B zL$_8hP-@OmF2yZ!d@Jt(byKBSjJ>}}Hps$^+ev3zL7OAOBs-_L$HwSu3_oud@80vj zs>xP=kl@<JUM%4|9LSe(6BjvWypeNZpO@SrgncAveO7ipHP>KG>1Wy3&S?x2Nbca~ z<Qm5<Om$ZKx$(HF+1>K8!lip84c6&Q?08C~&CmQKAPe#3hW(q&xE4|A6HaZ68l%}9 z^)#q4jC#U>kD9#8mC83`r^!3}!Q?=Iwv1gp&Zak|B`~^!$R1>l3`JIBkFfU{`fZzH zI0^of8PaH`rsy{A!BY~`5B?3BBSaTm#=u!vjLbm$Hze1&<3b$f0MF86f+|Pw@{~t8 zv}!mF5X>G9x*mF)r8AdmFw}o^ze_fCFz;~_j=Qlf_5&g`UsF3RW=hqd=jEWl$>OT) zx7iQOhfw{FvRZQb{0{alT}l#Dl3)DkXVKfS?p4U-SdW|XP6_F-zEjW0Y+&1;l>*`s z+z6k{mctJIXKw&Tn7b6izDF*~0a^<YvEIdZj=Lu}f?VBEjV-$1x+%QGNz8^#e&Y@A z!~X?~TpT7$-Ou~1*DU)B925dx9fEphv7Cdcy)O;k#j9q2<9W>32Etn-%x85?f_+1C zTllO<<?>@W+m58e{0gK-^uHnXAPBbcN2;|A>TRNCwrHMwa5bhsrLg6wZyQ$kQ<gb@ zC(4x7@`&gO|1CQ_muT{bGpH}NzrZ@rMX|G8_6=P()m~ny->98%7FSx7nQLQApZMB= zffAYc$x&kPyT@8yWY9kS0^n!0>2^!p7yITz$BqP73f!TAY+ND|&=qNCu9?Km1T_UV z<m!zm(6S_}M@2{uL4SI^d)sHg*s73)De_pWoObZ!A>y{TOosVE<cL>2gRX@=TGhRP zD8Y9UP~awa2&NbntNIxc12<wGV|!5)^=g%2l`XQcr>P4*98ic;SlsX=_@xVb{duNe zQPfV@I+34;$Ft*Bgaqs``f;jo7RQ4)*P?F<3YPBszDVq9D~V;T>wNydOkK{G{*FKT zF~Ok~tW@J>64_M`h?RboF8~ERcASc}?)}Ev<@{$<pRYW$p_FE53!fPox5-Q|S6kpw z6HK0bZh9l16!BtY-TH|ZU*=9ePo)0%RWiPoR+FJ><XAVJKe4=1YMVJSLAT4qcRT{) zrtTizvSuv1chSE@L9*W`mU!8*Qrt*f3@5p%GZesvij@3rtxoG*^y&@VP2Kj6z0^O7 zj?Kv4jO3_~DltBF-6{oHzuJfWW2sghd4s!rnh0Y}2mO!Gp0!wBMCd;@K`&R;l;Yvs zXS_pKi-Efy{NAw%Wv<>@w(p_F<>GiV5=xu&!4I(wNe>(84GS=@u}R&0t~SgBngGo4 zE6;WRN#(?MV~9Qe^PtH@tMk_uf(`e#xcyvo?TwAP;@M8AxNYd<e>nW<>Db&);EAj1 zlcX8^#Gxy6697`1Yk-WnIKtvzDDha)&X8!e3pY~Qu+?upizg_g8T%18{-;8#yl28> zOH$M_>qY56!qGi7>xZ+gleqaGMYU_-y2+k6DNIzobFU6*gf0tjEL8?wxKMpwtOtv% z;?=lK+w$@@8u_-F%f+XOw~X?@$<%V@tc&CENQh(@V}1#wrExy{P}J;P(8{TfD1Az_ zq%WycIFk2B{4Y4`t3@O?1t`zwt&uKol2GfkK|iYZr-nEO3?=UC`>vfw+HllYyr#m> zcCjL4c4!@tTfe7>BLZgmdH0CuEU33Ury|!0A$>E=r}}loiqOcW_++tr-GC%~>R+D} z6+BG#Sj4-PS~#>Nds*@8sR?I@it**=)E9ry30%KXkZdYQA0!@hG&pPaL;*lZSZD9i zvwCz?US#Vnr?i<VwZrD?{-Ps2QM7J8qB$-Pt>=H(>-lWhcLMJ=9pfi^lqr?>xWBYd zS2s_TwX#Lg@X=LFX#RiLd(W^YyQg0?7DPlWARR%aiS!Nv!AGT+h$vOM^xgtU0*Vx+ zL!_5T7wKIHML<eGKtNh(0s%w_NT{Kng^&ODJ=fX$?9cnddtLfLGxu6EzxmCqS>;~$ zkHy=!&)MGqyWktyt2X1i!O|6XLUfLD0`L~#V3(cxBHeub>@s2EsT5dd(ap)4sS?QK z+&dXrN0v0-UdT<pSDD9ft3;pvr_z{wQor~VXlZ#Q-xI_VXlaC(C`ik}29BiZSlq3- zt?S%4&^q}R3xz2Mgg00W{Wj>!Y#juVw79&Pt3aj}mf1ivYj$+@Vb`?<m{n!6lpe9{ zsBzuJzje=CmFnq#YgJ`$iP+GPB<-Hvc6?N<8@Zj^Vg!#lcBVNzA^<!aG`+fPoVo`3 zuU)Z7kE6?fm;_X_o7DqJtS#!OZY}Zh>S0dc!2>dE2Uu{LPi!phdSfcs@~rc+(HOU~ ziFM1}Mprh?+DLuYzRb47lbD+65z`B@H@-Q1U;q7><?(aHg10AzeosmLm@aKS*_W8$ z50>2Yq7kJm+E+7tm=`Z|Gx(nQHO)Kj#eVRu+@+!4MtC8+N5E06=HaY&4{v)Sy@k75 z1p4dmB;*IYg|SoINh~C9u36J!<)1_&_>`e~kxL&{^<S^>=F|(i?WP!|LpEl*CZDE; z(phYS3JFg0Q&ZYdK^|s=d?EH$19QYDZ*(<%(9w6Jc_9`YLmc<@k3QDsjB>U-=;jI0 zJ@QxBEpc1yaOO6YIN*z_MzQfllj9n|Rej@Ss-aykV>lUYmc{UBhbemU1K{a_ShV+i zO7t~3v$dfWx1QluSiVuxool|uw&ai>a@xWQjI)T>zcKa&VA*4E^@U_{-ACd6xKAL> zuC$dK*;MgrpZkg#I0yOM{X|{s<F&^2Zbv4t@FwfJWF*)&<QD}uV;LWlGt3>!LEKSi zbOA#%1X6F&b+gNqP~bjc6$;LQY-rc`V0Ag)!p#trlkv82o{;WMU7VMO3<R>4^zl~L zS=Et=`0=0D?BG5kUo|9wXbc;X*uxnri8%-psT+9lI=9IYd@CFBtyhdju~vPj%6lqP zyKrotLS0gUb|iWGo1Z}636#Two_Sm6=Fy?E;9J)(&*p{(iHNuAE_sJ(mRTiO7ZZC_ zMfU4|TK5OVHCpK+<}OULs!jrB-t}Zw<U=5xW=x;r=B0|Ctn0wuiesM9gdNc)B9{0* z;XB7xF09rQzj}V&*S?g%lcHd)eF_rYD)x+rez%zVi{WCIte=0Xk~vy$v*h#h@nfBb z2`r>!qZtfCIM~iQQJ>!)cM8%W67iu+YLWSE$)Ev2eyfbv+}Z2Ux1v~ow4YPyL?bhl zpqXdh!L9yw9tgx&L_=DKj<~B6Zjx6s%B#SJxfNL)`;HdDyY|}g!z2jYz@ao^SYo-p z?B0nsmBmI$V2jy!;YB{16Wk}*Z>gttxKe5S5pZQHMS&!NUN~-4Z}1XCDmgzQd!=cy zPBiel*=&yhtUVg-sUVtcB+x}IuKhLwc<^Ow(npG(aj7P{h!cUK2fq}G+a5I=e9=!a z>Y5SZG#jow1BtX|dJ>n>EB<P?%I5pG6(UDcLP{|v*Hp>=Dz_utHiQ=^P6jcx&b=Q# zkmnk)C-~Y=t)g37=*3(8;u`vflwpuAOzhYDvJ#wg(zh4Odc3UxBYt@2YQcDPcYj?; zP=o<_REn`Gb@3yS7Zu%4O(^kF)<mr%*<2F75YYGHXLwa{IIj4uSOS?Y*c9tqmLq2z z5#u=A`gOvFg(qZgsd6Y|n-E?D>9Y`1uUtl^qH(EX2S>P%@tRMd=T=B2jdO<soQ#XV z_Pzt+%%Z6+73AfUT-T?JglEhPvQ-io*^-@(+FUuQb$F81NY+7iOl*Kg-<33_OOSha z#vuZi8)wGbN$&Q5<1a23???bGz22XRqn#Ga?9rBxdr(<<4suUGdr&byED`rycY1|3 zw&?1BaR=#Fa(RKLGapd1Hq<_bWpQ7j(x<CG>IwuxE>xBAPHHyUkJxRjH_CLAK=C8N z{!;8fL)mE2*!-^vvOB!J6yH??E3RKSaYDQ4o#@*+XQ$uT3h+75@w1dHel$O;g#RbS z=%_2y`E(WCjC$YaWH{vW4TlE>BFHZzoMkuxgI%jVgS5u6d6`0kKvB5|2j?M>=x#AH zC4CWmDx-a+QKbtVcX$9hQKUz}T0@1z5|||lfrJQgUYIwSu4TgIKB{!lR2IHq6${3X z-X1u}GbS1;ltQ`Iroe@!4AsP-*ei(F<r?`m{aFokJtsw5D!4lwW<VTzR|&Cran4`( z0_3H!de$cqZ%q6n#<);AIh=hKSdQzE60%kC8&IYcBEl?>%)!eG4T*}nmX47XTIO1* z8O!0!T+K_|jrYn8E4rKRHyt|VRR7y4OMh9nwDfT1#5Jt5mqH$T_cZo1P%CgSz*bE1 z48-M{VSv^ziekr9jV_I=(?X6jP2EG3);HdQKB*e-HU3tRDoUXv#GQt?FlYy8bqOzl zJ=pPnsWTzXKf$sNO@12HL(W57`m2-Zh)JXlk5wJup8Bo>u`J;#;3(1n7S_SC;hIdk zb+&(DxLti}TZ<LR?mMgDNcISh;r%pRx4)87u!=cHI(mttOq6iB#A*$J+!dyJd069G z9B*1aZq!^g+z6p-kZ-S;>M7pF#Qp8DEHT(E$1*1M;m4d;_@U?fVweEQ*Z#u|WAmvW za_V0a7*7J5A&kHI_TUqDpqJX2#_J*W0Yix=dBT)BQGE_$XzP8(`h+s)EDCaN_e6f@ zFu&c5cS>g{Y+o5(A(GJ?UqD(@@FQvlcCR^`-bS-E`5hl^?5s_%HKzEdA9qBpO|!A_ zIGq+1F0$9<`jpFcwN-X>0<Qa8whGiE(v%%dZuP(&Gv+si;ugPbbi2hLY=8q!r>_Ww z{Pc(by(N(^^S*v}Lc4-dTh7{_XN67a(2a;=g3*_~&Ha5{B2?(^_%nkXL`>pC^^J%$ zcek(rjXwtPm!BEe+7Hz=Q0d*gSZLdk&DwMv3A02*%A0&Rg0PDkeZQUMZB8vr72SL3 zk=E~A>Jz?giCJQDE?BRt@?hn<<l}ORZI9D#c=u69l@K3m%%am2<?&P;QY&6I+o><` zXC`L*E}QJBkbZdFmPE$qX%4yQpU*C(6~Q-4QrEavQ$_nI<o?j$gxkYORx@XHegbW} z*rq?BwSRe*$XcVW4<{oN66}aZ=?>0G3H0vOcjb}Y&oJwYA&2E0^RMTcE`0RqOto^^ zdidaqQboj~D#$3GYsSuX*7wjTIm1c44X@&3*I;>vT)EbrJ&eR`4P~fh694?AEEi|A zzX!vDKe8$=kz50sALd=MP(*IdSUnsnQlHCt)k3k8SA<MZ>YO8-WT@K9o`1kqjk~v+ z4EGt};y{<z7bIDudWd@m>{~TWTZ@>PccNBAm7W$|C1m|8=G^q^$8~TC|7v~F`@?T} z^ny+D#^%2kb~&5Nur0(_&a0$EBSIZ2Y6{aIr=%f~d&B(O^?UnS+l~w(B#vHN@75Ob z@EfwB*e0=x^cxkS>dm&r7;y|j@S0S_uIk<lCXNfX8Ex%&pUC6Zd;BpeH*a0sLec#x z=RtTPf^~Lzy!tTd_EihBYQ2)wFx1`83*q2e@(b~|Kw9+lzqu%;lVeT08eRQw3s}}g zxD<{8diYbge)$M7p1vV!PF#vPZ+(Z%+&1^FbCY8#;el5#<DGA;bs$v^9R{Tq`EuUI z9TD^GaVpS5PGrXPS+A(k!33i&IY~dqw6$~UP#)){Gx45g*Q%Lz4)ytLDGHH4dwJT) z)vmslz?>Gu%Z%8|@fubMl5m>oRTN+w0BJV(kA@7UB+Yu~L%QF`*T>#iZbz=gB3py^ zdg+8S#bR=gd*4N7$SkHX@G0<t*`L7mK`Vu%DRX#NblwRLofF_zuTjH2S;TZn&sH;A z4wJ+)BI*0wZ+!92S*Fq8`<xls2wk}cH3!P5{uHC$E%76Iw{5X^?zU2QBxC+<Vq9n$ zjko1ay7X19@7)<u1L9J7(9P~Tp(}>_bAI6(`oy1%b)pMT$oC(eIAacGdVA;kL;l;i zNCmjONqRM~<NX6_2Kaj!i5>MAgxdmLJ^h3n+s_t>`KmsN-s13RVKULt5MtVGW{^BA zm~I#D`q4P9h%~fqYKF)<)5P{wvsT<aXVl^Dv6^&~lnwLp-}d?%b*8sV2cy;gIk5Y* zuA+;kmR4IM0`#BiDR%seanU&wKl!^OC*t4dHzsm_MEmrtQK1n~ug+k;<rY(Q>(e=F zF)m3zyU!EU9=%51o-Qpltl)hl=QRC!3?8a!Jg7-r;+y+8J9UYCV!5p2fVQL`)%PIE zCDBh6f*ZAy?5a^c;_OYjid(xylj60^LZ|2iCmG+{-yc<s+-#}-({b*0NxWSpKN9N6 z<5&y!QeLod0`H4e<08r%Ye|%|U(XXLoh_`*tp{bGzhwOX@h6RrX=ooot7{VF6SUGl zQDCjL^Dce6io^u8a__!rM!}*OzLpDI?9dr_v`{Dkd%a;5IIQaFa&HQZ)iU#Et**-S zm8d?dJnY#}lJ%Jd0m;v^EJpjlaY^)H)^gh@mV2kSszh%%=+xLk-^AtDMdA!ziZ*g` z;ZrNbwB$28##;?9;dSLXpAWF%#4jKx7``Yp^NShsx83<>)|&Yt11PZn&MoC}c&Cot zBl8Dy3h!jtD~*%e&pkJ>EimJ8-T`}3Wbc|j@spj~3FC{gcDhd-`!=6DAsB4yCJX<y z7<4fWad)CC+|r04mjBUh+L!Gm1@i2bX^jC@UM3X<GtZ{M5aaNJcae8Iwe-?lnyfo; ze=sYirk?4!8an0zv`<kJDi`@g_12kzvD0mbDuqSoXcDgsZdYBb3`v(xF`^2SMCuy8 znr=^+skE`Q4-*qRsO}V%yh(ES>5}9>G?VpX$0s|Wui_O7)}q7d6})>9vePoBuN^1* zJIE#lQKMF&=6C14?-#emd%I3Kq?1UNtLh!$9h*ti%{kB#iAX`ba4_pE7YOg7+l*t< z82sAVxjRa1yBHh`hQ3L5@O9vfRHasAzZLO2z^|^j=zVL=rq55k{tHYJq|HyTrSoI- zkAfD9s=q5fC}=Xw)Zu%#GP3fEwG2TH3)86<F7N2%hfN0JvzBp`xCYOiW{aA!aaXVe zp3AF$9R!`wxMlz0ht+VhwZOV2el1=))nQvW!Lw%I(uuCuw-Ryd3qSagkB@GQDQZBk zTh&z*QnFX@?_np~rQ!TnngW;s!ptvEH$}JyYRBd~-dBFGH_p{}(xct(B||a#TTHSZ zN0R~PG@x?Z6&$;!&#U|D-AD`1xRLCihFlMx(D^nWf;d%mKMrzL6{$L`Vjh^5@LA>J zVAD{W9M0_SXkOS5!bmiMMbaf#^kcwxhkgk~gue1`nX7`G?Zz%ORtXi!w7ZT7ZV7&a zvE)pnUN~_AV3oYv7S?Y@Bd3@;yJ7wnKbQff8&^6z8d3D)eQIp0?$hQCvx5ub+W{x3 zvMHh>{`%DC+CF9OKdLW*7ffb9EFWE}(22d6gm^sF?Au%iEoC16RKTYjS^S2|pC?n7 zE6*7&-RA&?iS1hH3|SwV*r?17eB{m^;>O3i;vwgg{O<BcWAFB>M}AV_=~Auq0sXUx z6{j3Zam;p|p)K0gFuk4vtJH6Hb3-Y_VX2~ZjaI@GJhoh&*IMIt`eTc>RKRrN@A-Qk zR$43epFq`^bmK6j&u5~te`GsvwIcb!$@7cGP2fceY18VCm*ezP3_>K2M9SWB0rk&1 zs#?i>W%dQZmt0n4n0RZ~MplSJ3ul0{hF`nk$~_-q3T?Sbo8=wP6Ax=Pm&)i}GuLBb zA;Ukk1~HJ!7CkeK!#`4!c$pgM%HShE!BW5M;AiK#0%P0PafFpo+p86_z966)jO^H{ zbkE*=O^!Z!`T%3!O?SS6s$plbbkw{cxYoHWNug|D`9qI@|8g(MdVuL#HB32AP0nW< zWE2@WXPrH(MSi5>WoRoW`qB>1Bnfuu;aHtc7x`Vcq0w(Eq5Q28v=j7paA`I7t`h3v z3%SwO&i9G6D5Br;UF2<#R&sPd==Mx|xxm+3vSI84NV_{1AHEnUQ;FXP1IS`JSQ?PL zuD1Ww!GF<MEpdJcR0XRZ(_kP=cZarLhGuc14=i0^XW72C=uLNywbw3%UA6V1np$yV zZ9TEp+P*2&@!pcSUH2dee8jbs?8On@%e-9Yp|3g7KcP3rKWXrAnJ*jgw9y=UT4-1B zmPbQ%BF9QV3MHL2@ajc&y|eeQkXrWaMdbm#Nj5ba&hT-ZW$+JC9pc-b6h2(V7jm)k zh{moD%WF_^KhcB5Wj$#tuzB#_bMb(gM_hWm*+%-j0`UN_n(d1Y_rsOyoW6_A)*tYL zGte9vxcw`u_7#8st%d2G`ZCIulKze^;l|qW2VicHCt1X0y?h|f5-8$x1kk=r+-EV| z#tm54+|ohC#KMlM&rSB8x<_B#ua#u9On{0@U=9Qs3LZ*rbasNtlY(K&Km5l}`ipw` z`=$f&8_khqvBAzEtt`#f*?1JOZf!*>kFwKL#_@J*$PQvqR`!L75M33*Cp)Ka5FD1= zm^Ds{Gb^m{G#tG7=Xv80M%ENK&smSr=#ns3&^=Q1xV(@OMRD0_ibiw8t93u1?87|f zmXlP~4qAn<|Fp6|!f<rOtASha8|Z$jm^SwMxi1YmAH|uuNC?&GmS{_(#7I{NwEN2; z$ReVpX}9(x#)zi@P-{7teK`+d%-7+!R-Y&0QPZo>4#eJYj&WhqEKeKmU?oL`B^39J zeq$-cZj$ONoSi@HZ$@1Td-sBolZ2-~G_O%Qd&!b{8N>gKHGJ)bO^qd{qqHb=ZMQ#K z*XBOahui-tOlyrF2|w~QxEPBdW(k61%03r#D19OMP&c{n3*8x+^j$n{ax}t8TK-4R zT@&VqtG4d%gkxcTUME_kij3>MeI9&UsWW5Yl<A%S(`;=VQRn)epF(cZBtrNh5j#yt z2BPnZ)-b!b1#RGyLhYX;t)V_az>|g;SlE(2Z?8%A_rWXJj+(gOQ$PdWxu8Kt=!_V~ zX{<L^E^LxW4WN+R7K{~hHZ_QDQqIr28XM&vCU{17_4GOOXCr>W6bC?<L7rYt$-(C> zXqOq|w6O8f1gvkXK>N-qLrECDbjuo=!p>^w>_wWf6D0&rFX`{bCY-=fG2Np&?SV1x zntuDKWDXQGFa8*pST@k_`|8&^kS-r0uXFOcQPL0m$JI2ZHL@Ja;}7=2ck!r3vd@>M z`QI~JP<b4-aP<@$R>$NlKSkFof}E1_fUDi3?w&HbV0?TA%iSQe8v>9>c5GJas|~ey zKjzsws{S)MWL_Kqd^EOUmE*jJfaMx|JDUB8NBMmLH3^n+QLZa1L7`$fe*Hq(vgN<+ z%9DR}_8ZP&yK7Xk{2PyIB70dodNv&EEnd1O(R%{hg;&VMhVC#xiUapY20vY=5{pMX zJ%B6za4pRh+wqHrWD8J$EAB;(5N`o|b@!*h3F;6D5~86v3k7@8;Jm)Urr9j9Am}&p zIN7KsoUF7_=^x{4kf?u^-c@;_<dG>;*(5DS%FdhGvPRCH4WIs8MeYkEgU`1T?|>Ft zl2&MPoR>t$Sc6L<)uBr}JeK<OIxb%`qvk$vhYeeegwyWoq%pt$BYbP#DEK+-oDAM$ zYja=qC}iXnz)Nwv@@T<HDu|?`TKR~Vwx_4qLZ_FdV1rM|Ck~9QuBIWkYxPna*-e_! z)6-3IP`^SKgx>-2FmJ<=B@r>OpBh%P=gPFmR5hfk;9jx(Y-#=JVscHrDsW8!yYqIm z3^TkW3Fq(cSCAbFGie;3>jTJm*@>F!)6=<rFORbL(CuIgCv7z*q|~ebc}URdao%f! zNCRnUQP=*#;(7?-yQ>~irLP{8&vzm}#m$)6z%7^L47$5d0#a(5IlVRq*3~cYVs8o2 zgl=SP>C?h;BL|h7v_n02@36Wr53VG;W;hm15&V3T0CDL%bUbNB?k%n<95k0aQs3Xq zf}fVULwb(J=?@15Z8k+SDJ58qjKy~tc})LMG0p?tXlqW8@X4~A#{C+M+WnX#I4><v z&WT>R4oN=`)$4qF&dIYLesr|c7Rgh?VEescg}-Dl5by4~xg+DKhAzfX%ORbahvgH@ z$Aq!mzI!)oc-jnlD@0VTmmr&itVY6C)nxIWfS&@9mlkZ@XJq0L2JU@rd4wG=WunR- zKIwJ)aQ*xU)_Ghq#<ntjCk_9oHT#<~CHwI|9kG3VsZkqwMLq73$|oEkOrXfN;mMu^ zWU>*@Vkvg>WKyBxeo!N0%jr==St&oC8`F`+DhZ^=Lc%PK^m=TEt9ESR*JWRAUO6l| z#s>jq(yzlS2K?QuTD^Elc-BK_gSUj2c+_=o0Mb^f<%%W<S=h+R-8Hu-hl_W+D8+A* z!q?Z;lWq*;<2ShXvkp}B7pnY;Sf^%C2vVw&=pqHP#yp#TizEGaDLhPoLRgU&FBuCp zv?fJyNBWl?OY|fPwrw>6yd0`2q9h64f%)nzZBbz#lHOGR7%<}o<z*VDwaFa(#x-1R z>94^K_m)*GH>PcDQR)=AOh+AjOBUP!U>dSjL{tT#5poi1`|(htg<H8^bw?x@xhgNB ziVu<5)==cs1L?LpxTTxheZW{r1g(tN;d~sh`5eirz(g)#rR-o<w<BtO#ETv!!;N0~ z)LkyX_v>0~4Q{~M34XoF!^;0~q!NX23om!5sQomMac9y?_84KPJ|#(dK0W0SRU+dO zs9k8U+t*msQ#`nG-lbr%{vEGRK471gfUSYHV#svXPRK5tyBUds5x=%J0i(+`g)|bZ zbd%-iUUaIRph;|SGP;;}?7NBnxcyt_5_mnFW4b61cuTKq$HhSmQ@&D~n}$c3rz)g4 z{=<H}Gdj=u<d{pJ0AAZHX#;sJD9zMJrl*(>qwf7~#LjIGk8&fSMO5klB{zL=4TeUu zdyQV|&@oU*ao#$ur0-|si?$k}Cnac)%|E|gGKAm6a?cqaa$8Ra$MYju%lkAj{5r8e zD@=&kMi@_bU1{}Z!N>khTR6Y}s2Jw!pH8;%sMzkNdG&JJF={T%tBN_7qZa|Af+P-f zG<^5mDJ28HTqh7*D%CF$&S-^VqPa#dI9A7%f$XZ4SL=?4Vm-r+oEu5h3UD<jwq{^P zB1doX7mbb$JZH>0GO%6`h2loPlNj0%{%Y&hmT;ca8P&MaBPrN#U4lo+8leC<)3=vR zWHQF$tk8oQf8|eqwtTGHReN*FT-7+Y=u33EfT%NE^^f5s<x}L!B(BIXE8TdbVc=5g z?C{qKr&Uw~L;aoHIyR81@sjCTeVW+Cnu9eC;3bN}hT;ZTg+0Nd+AMD=gJ`GGn}&G2 zI<;BOB$r3adR^JQ$x;Tv1>HNSgb`I5y+JzGG+WwJ0I&PIG5TGSF{0=y5SIo-v~6oV zs?yF?RjS!kIgBUBVi$+99=rC!pjgzUak%MetFq11IA~8XzIu-Z&U6<)l$?5(gm(zo z*c<89CoxV8aBmq(e2x6FgykkdbAV<lh4sa0fIr9+Gm>)<==m1;yh+;eKZ2S!+2u%h z0WBZ9F(2y0&aP#gEr8TM;6wd0ls14g<~I(f4j`@GRFQ5mf4?p(L*htS(eH~K)bsvB zixzT+apSy)KDAudno#MKAI}U~rO9T#S#xg~R_i)QDr-Wqw7&74GqNIr#qF8K4tKfF zPMPp?IhRU=q@5^akaLY=I{5()O8HhnkVundS*A8y?H|?cB3SeW>jrhc3znD27K&kF zy+YBgPHIN;Tgj=?r0k19&Iw06J?}bOK7KWCCsZb8<#3_#`|m(Cm>26iDRiZ(Yjxkz z7T$m>x+qXGg8zc$wtl-|_!#Tc_&JZ;GPu9sI`k4eAIrUdL(W2<zSnZdlOTp6uD~C^ z8v!Sez(_%!{;oUo-nMc*3v)gmm5gvJ=nHZ1Im=@GM{;1L3Pjl;7kB)0yp5Yc*o1un zwc+mvaR?C<Y*ma53^Ely-p^1ks5bPE`W2-u{A2y^#vSUAb^GjIBcfoMd`*Y5*%Oql z$0=OKCKsO)Rn(!<hB`;B<pL0?H>n}8oARXW72gBDO#3eFI$hoQ9#h5wJSq|4wx*5C z*th@@ilJHO$&QkcCQIJYJ(k{wzn~QK*$QvAW3<I`d&xg_(!Kx*i4g@d+~`yl={3w3 z=?axpcKfMo@iE)P+D=ty?Vq9m!lI<vmKU9daI^A5Obl`6OwK=(dMDXqT`8dXn22pS ziD<}=du{^IpcO4?>zIX(@#MwIrwEO_`Ur{bloV$a$aghD&-LjcEGnAqCoMf*sGpk5 z<H*~<r`V)QlwPjkcLiB}G9bdz2;#ya&4|A5M#PSNUG!7b)V%0QYl64NQAvKt<3LaR z$Xe093>l3|jey;hCgCe{pc0sJu1Rmdu~c!pzV?*Qv9XB9WrdWGNY1=DZ9pz*?U;G2 z6aIUwY*^s{msFJG$IA(b?eX;MkoU10>pXZabgE~sfljBbmo%X8c!5<tBOjQqfxLS9 z<!dYj>6#k~)?3}N(^FhX9iDX*TP?Tl-MVLr1+^l?MM|0-ecz7g6V2_I1=1?cC{kKd zKV|45d@(evIW~&U;}irFD@x?a=0c|jC8fH>)^5F{nN8<}Wp@eb5Y0{yfoWp%qVEdj zeRZDta0>4bV^jP&o1Z|O;&&i_z{wWxdFnF+pNhDU1jyO+Pt{nQPGFhS5{jlW9lH_n zJR2`+DtZN?sjS(R7oCJ~lc*WLa~fZXDQt4qxy#`Cob5KrCFL=MAs{slc2k&ypD6Tj zZ?V^;ZLiCL4b!#dPk!N;<M`7F1HKY*;VrwnrWmNdbI5q->Qf382<!sSn7Bz7r6?}k z%Pncz;S{8lm*z*`Hz#5#D91&O_az3QopmNlZxkZTVlUV5km=OyEGZh(`MI5i-4rC@ zS3YUqj>S7%ah%Y9#5$p#?sPlrPjB7qB=rZ8KX~w*=+tpJ2MJ92d?m&q=$wyB!Ob;g zab;o#A5~!#UX)5YATK%rn6<$(bjl59lq(claqrmwc%QRR5=?V0ch|k7x$$pP*_`NX z<0rPp>H}(e)tgvcr;sbt)AXCMeJD?BP6*B44zsCxq{j*G=+hS8#rbts#6=@sSinVH z&T*h^JFm(H6=q1=hRwU(!6vCb9~<D#uNPY=CxA9gl8ru7L?d!<D*e7z9t-R3QRNN$ zjIx?$*dE31RmUPEgqs<qPQ~_#;m@bv*CAqU9}aa1A6jdL6*@0Rqx9RAp?r4anlJwv z^bQgGQMignN}3?h8V}W<*72z;1M|DYUuXWyW+39^{&aj@ipO*)<XLPV>n9(w(z|~< z05LcAycD`4l{fixdLRT}L9SDMrr<x2a-dUF;+Te0xHYniBR_GVjY?B)mP-A76x4Ec z6+VaC=_-=s1&VyJebC^EIi`C|e}7gbs&ui(N5I`yGmMd(v3;6+<Ep0<>9E#JCl2K# zaUiStvrHdj3aWE1W32`GexKG+Bqjy3G;1rXK&3Y#sd|bliH{ux8Dsm5)A{^8A*fsb zdgnO@I@?fAFWJaeJM@mWy$TfLV;(PBD)6^oMWPDsYlp-<yDg)B4i+rHUZ$*n=^67c z;MB3OfgV*2(6nxW!xC!CaekHd+(i3nz5nQSlf<EMw^|$nt{qO0ZPb!RJx3bWTI9D$ z`dC189{kl$87fWL)3co7H6|W|ui$N++&K01&A$%$2HqH0&9QX4$XSKy;>^wV7Pk_& zsK>XS7BtoROAJt)h&9#v2^JM()AJ28vd;fgM6GH^YFC3E?|1WAo2vXrE<<|JDkt)n z^1!XV*$A5Q*gj{U#*B-Jh<4dW5QD!4C8J<ECY@y$?(o>hbzRiwm-XeeS7PU4qw_wc z_7^WPZgh4UncUTz`IAozMX(mh*g-1GPJF8)-%HxRtr(zS1Ct!jv|picMs1~>QMMAZ zv&F)wzQpAp5HP#>6JM2F=)$Nf`|hS}xUTI#S_4I$!G+H+CL_{=C$_KNqx_4$JyAvV zd?QInW<r2H|E(l`GwvVM<(e|c@L%j~)S)U7+>4EpDjQK~{F0c;j9n*BFHc@(cHOv4 z+dLe?_3&SifuR1W=CPm3AH`@vF5R!Yq}QQLnrwW&b;enLXZ@TI#orzciP$>*{2CGB z1HWRejP~d%J^wGvqS>jTtQB-eO(($f{{^%f@BUqbwOnzM5THJ+6U-hj>=p|%ma1<C zNL2leNZcQSGysCYN8qzvAFYy{|7pqsi$}x1>bJfC?{NNYEEn%Sq1mA_o!dg0*Yo3g zNoY(QVjy6R9{|t$7cnuAMwTR2t#qf(g^rhT*z5cLNLc3QCn0{7eGVJfgHZmFGezZ1 zPv&?al4D`RpXo<i1o9_J<tVv%hp0Xk%kh)&J;8P2#!t>(QTT%km&}Ck-Fcd!SVVd5 zC<+Nz$0&xZxg0!{>^bYOY>2D6-e?j6lelEC1rnWvvWt!b=+{2oNi9Mk!ei#?o2& zg~Jcbi7NXSC(K{bmtOn>qlEN7MC=8&vP|X27<*rEOV~ZkjE<Kj7dnKMnMtIZ5xhr! z61OR-H%QNsnHD>Iopx1@m&$!86F4|7vWt=qc4|BL7OywTLALMxt0#DuOJ8@t4Cz}T zF)`*)HBZnH#SuO{M!^!OsPuo3@df;e7mZ;U)Rx99peQ1nkt=1efJSMvc|mHC3tj)z zrRGxvS?Sq-)zg<JJs*0QNgGr6yj(m@V!iPRRZtac?4Q=iCm_@>+5Xj!4~-abTD#Iv z*Z1N~is2q!1HA1We{l@En9=bBoi`(K2J%DcU;Vnd(Un$@q-Z&+FcP5leO4-`)6XqK z+8p~9O=kT0v@&!sntk*+36C0@-Q8e_+ls*5xjRp=l+x?xmLol9{V18GagqE#jTLaC zzvv4ojWd~v`nP3-LP^-XZpU%*f_JCR{~1zDQA0pgGCA_GWUW{!q~(W9SO|XOn`OKx z$W3E^g0K|(3!B%GJ)Gs>xP;R09BmZ;b##{l4P|C>W2Q8P|6!d&xi{E+L{4f|I|;_@ zsa>jklCMN0t%V&NKY7g`dgjMpiiB~aStUQp_A1)mbeuVAyTo?BKmeNuI~H|g_J_>< zRj3LD!}X|klzNr~e#i38sT(Yz5J&s`$FZS+nc9B_08>;Is&9&Ip|=_Ypi!Zm=3=fk zamj6bo3Q`!R3hYG#0%39b>Xh$xDOrp`0C&>^odC2U^BfB976La0hyw5fbDX=QI)i+ zZX<SV{cC%<9Pf;=d42U>AXxq#P5%`_E?=rDBi`|Ho;}n4yTsuBQaoZ0Ap~e3B>0yG z(j<@C2lHhTRw#}>{1o!y@kg$AexRw~U>QULWb>bYeap*@&H)#SRaND{h{}x{syW?k zb|d(W={$jqMBrR-6Wt%@&f^E?TaHYbBR;Gcx~|qeUgFGHO+nn%I5j6h_c{Bo&<ws} z)CyW6(RE>|X*tqj*WT7?5kI&j+W~Tc=3lS45cQX=a==NaB~*j{mS06`&NDE{U#e)> z8N4TX3^DynIZAHy)`Fyo!!?TmXQe9L&02v9oZNpH_wH|hlR&BAcOB!n0dBcP0yUEL zs7P=cNYy&-OYPq~?ef=so~S+pNnT_{KMcD@AY4H@=_IV75qFCYDW7nkVu|=SxZ*XS zYQ4^lqt<HZu)HbB=bwt|SfUYk2_9IG6`_BXcOYVo7v;i>_>nKZf7-h=yLR+Y3Gi;8 zm8FzS;-%t$N$C^7qNT*SVF8)%9up~Rj-h>F4`N|xqsETfaXAS4Uk8bk_`E6xBn@q| z`wVi7yDR1Wy)hviXiYYhJaGkL_18fKTxh7aRB$P95Sju5L*6y^Vhgp1h2`bm24e-+ z-`o|(g(f@MY~c;_*h}-Dmvn|s!%C%ZlROMge_EcDhlu@UsR9ay-s`wgePq?pST|;g zCU+z|(gLJ#96uiM)n|G6<gX1jME&&>8y2QEc|8t$pA~ODO^fz;0{EJ76U1TupCO<W zn~b#{>p>VhUJs9)o<!@5rm^{Vi~70f0l6_rpq|zJe_3YFh2}g_&t46kUXhaCXnk=W zEs;0Gl7P62G=T3~o$CB=!MH`>cdA9Brh1sX!7?-|h}Mgo3w<on^(aE`2ie!xfBmHn z4Fk(XJ;U#DzAEE=@ngIup{M4+ar~uHSC9ml{@U@JsK0eWw^izi!}0w^`@*HI-$mv9 zvoYAkrat12=U?5<{Re1XE;KnQDabL7W_z^bXP$rC_Q(r5IWf{Ej;ws-+$bdWZ|(^N zHiIp>v4aXic})KxOlf{`W*Mf&A|pZaz-^>}pyBw-&o+F;Dp*5z(4pDhn?F9-HD?%R zYcllGxhn-Ezx_^-m3vwCx6uG>-e7h_nFDK-ob%A$;^Iz6(fRG)yM#P$4VF}pY`*8g zeyXfMUNTA7O6Uub_z)+=G2GiU$Ta%BzjJZ`Y8tVBbhzW}6)AO>v}tgq^RysDnPYL7 zYnc-*$3?ni>i!Vzar~<lOscvkXC&w#(aOC=8pCQ(wP}FjHq-~H_<Jf622GQAFgo!H z0{Ov}_vhJ3j9kYk>m#<@)ET*Z#3hd(N1cObAj#OIDy$pUdi?~5^m`)nbi-!=b88$I zPg+*gEYyfsgNA{YHD&}Q=U9i?Inc&w1J1-v$V){xW5@DmMCn$LDXJyUr@O}PT*2mz z)ZLp-fj}H$2JKKov3*1kui8=^G^|0wv3>qX39;v|=pp#%|NgO}A*U}q#4H*=X#3!S zlf@|r555rhybSLi05syc_zS!neoh72u>E;z#`heA`v&(AR~RRnW&&tr+w%>)!l4xl zD~bAc+2;l1-WlmU34K0Ns<q!n#Vo5&MUgAmf!h3a4Gbm_8}7XCT=tx3?LSWn5j-~5 zo!UXekt`Ldr`{)}YNZs$Av9fqH`*p&$vAe8bV~taVtjE^!4QZkyY+W2HBL0@<Y8C7 zwB>VFXE@QuN|9v7kZ-D*A2i}sq1?6lODV+4vHUxx?BF+4Hb~(RvDgh;R8DN4ij&S> zZe>niMN;nG#W=(ZWUPanA>=cibee=d4+%e6xY=Q0VypJ8v9qLjxsu<6-U2j%)CNPv zJsRnhKQddlU%)z*r8(&1j<65yC)-s|bgwD<T&`K&h<}ccl0ECArlF$>wT*kXx*<&b zs2vwB(f2j48NfqDbqvaxu)F<oG<|uWBE6l7>B->g0AizefB%4hBdbagQluw17);uY zbxR+l{qs^bug>$^7y_iPD|k6^{oAB$s;6;2t&9V9!b7h-;;A=X05-wFe7{>VHEUY% z4}<LnyM67-!3qRscJ$`dLc`dvZEqCcZzchfM+zJC`w&g^!V@nI*@WvKPhBGBCKsX* z1C8*uaWhL5-nJ)efznt<J}?!ST;Lb0=QMrBjq&-G6#g_nUUKL;SY?&?yhc>gWPZAA zhKT$rYD&cVoY~R)5hR}Gc=>SSwllh1(nnh(UIpqi!n_}@X3PC{&)O|i#ycVr@j~O- z4+%Ow>Sdg+_%Nf|)Dx6tEDV?6l-DL{8&-Ug^CM$sUo>{{rejv%4t#g`6h>x}@VeK$ zlqSBufUBDWUD=GxbA)f$JqebA{<Fy_Lh_Jt85-07i~!fperVRQ?8MlWgDD>dH)`p( zp@3UqR(rxMzZaf_s55E<q~o)R4a#<5a<Iw-%@u&=7#T4d<}kxBE4w}_HY7N1F_|kM z)Xli8Lh3RXvnT@F{1cs+>tCGMA5R$;J1x1d+y3q@(?Y>Yx<|POO{fwnmT?JUxYYt; zbuwQpVxU+YUSIoJ&<AT(t-}6V(1{J4Ho={ga(aEcG#6$hhm+y4eG!%7QZl_w$|?8F z3l*T*3Pr5J8qj08E>TNn!u<<2;C5Qt2zU&aa{-nKoHH}|Jh>n#@2iY~mMaotU}|$< zb!R8zLyyrJtJb=0GQt&V1Rg1_&kh)|gfR|TJ1!<~EbIM@<t`B<ouaHSWf-m!wD}}M z)wOR|4)#X(>j-tTTx*Sw7F354%=UkS7jccXPa;DHw6=B8D>-&&==ocG#oFn0S=$QK zO2)y)2kYDz6s$(>)DhsUy$Wf-oFnT5nFEwW^4f%-GUjy<ds)QYKA)fXLC3w8UM=RI z;huzUMrWSj`Z6wFfU+Psx0fOqITmE|wV=EV1v6GYd<ih21S}B6oj@{_3Vt65eOkPK zPcG8ijY$@;v`J`U<)8OtK!)9a^i?ObeffQ&3Uj9y8XG6^&yq^|H>)p^BR{d+&X)r& zmrvagIt>h6NH{PfzqM9~J&oli6jUE)ht(_C_J-nXX1btR+-N5n20+ue(qg3W8J(Q@ zG;#eKq-<KDOQXh|ga+T&B$t|XaQA`7_{F#5dZwIN#jFZnUrI8(^BR7B1W2#py+-Px z_sKEaNr90n@Qm_6$>!2luPdY7rrdOujLsS|*u|$fdP20Ngsl;`zXox`nbdz%JsMFr zxiKUzf1QB|utj7Rt1@MPB7wpe{xalijdB6|LoS{Ov2p7F0N+W*eHC<3GUN(XyCK*X z@`-_S6D%a+x-s`c&(^%6^XZ93P_Ic6PgSIrh5xgos_^DOE991Q5f*Gu6xq0a^Yk*n z-qDFeuvkK8uYpT5`FYaMr7E5e1Sa1+Qw*H;EW0Q}*8C(k^nQ&GEcV>sFOdf0K*NG! z*=Ndv&hcc{5N5Z$r#{XaR$xvvLa#Kbcw<fMs$(Z~^Um{6>ahsc0Xq*i7iP-B08hd) zLpcNgS`il9UQAGfkD5pkB;Sm1%2Soj9dKatrn};L`~-v&j3sMZR~4U~SQ9UCiQvK_ z!SX4mFJ-Qxj}Hj(oul(Mqp~f~bg2}UoQRejc}~Qm;GV7%rKp;5Uv0JRpDUso#HH$t zn;^B`0%0C{^<=jx-4fZBIrv&MJ0d$`nHbdr-QYkw4KkciR1I7fdk25{E`yJ|2Dn4m zHZ6ob?1fLtmr6P+C{ljKoRA>WXZIbykw2mZZtUZ^!MKd07sdk`!e*=5GDJrQ&kbxJ zZ2ztr!R5rtPk*12w<9h|M!f=rJ@sFbQ}hlYS&yQ@IFMt#^T~a1c`d4FR2meqKGsZD z(iUWe_9m?vw67eAtI6tVh=FtOEyz>rg9fBG`dJ$ZI=iI(tZy02lBCU)&Tor^(-?4{ zDz&0xQ}?*Nh$j)t^gb$e8WBS$Hh?Qf`>zPi<uUlCQ>7y69Bn}D!3S>pRby}mWaB0* zdv3DrrqoBl-wt5~<uSo%gB2eM7vhrFI2`bZY{g|Ja8<GB-buUeL~yRx%|lYu`M&9D zc%`7cOq|3KqT-zdILmh!UvjZ7^|T8B?sVj8ki%Y@X^2~gF4&^Osk4ystU5|Qka*Uz z_4m*l8#^o5P*_tV6UwTKJkN0FC#L>hov`F(Fs0>VrB;*o_Y(@Dhd{zt2NT$Os?hTC zO+q2yy8&Nk*T?&84oHWuzk@FgENtv<?K{JceD)6KczLT%K|X(l%8|ckYw}MRE`}Z+ zZ5@uY$FV{nrO|y+QBl*4O&bJ~e~kD4_gee^>;GL^aeTBdAEtt|c{j@r?D_xua)aY_ z5m~xt5Xi~j|IL>hMF00+Za4#8x;iy>{v2p_Llg%J%m4G28~%P?;U@TY)y<((XHzTF zAP~cX|9oD7;uD{){@QVh&)NIb?N`pbCq6$f!gKo8t=sQK?!G*819iG(D9k$!`}Vxu zqvJawZ@R+6Z=DXf@m~G(>079;4_*e|#A2nTF{u6H;bN1>#g##ep^wGCR@WAN_QtTQ zPuE_IeEc=El|E^-)x@C^`#*pF2Z8@V;D1Fx>>|AhVm%M(FfmuSa`aZ979U#>F;+~N zn>$`RK5SwiY<swQ_+EH??|0d^*A|3umdEal5sJr9f!=^9U9M-=?VHjY&Cd?*NvxeM z8DoxG_Ub41VU3L*f8#smN}%((GAB$iLb2yP*9)ab3a!#mJK6r+LCI{`5KaC3`EMFB z())H^Zbzy=mWM2No@uW#dDT%N5{PWC<XPXX2{d7FKbo_ct@69FQ@3Q!eC(g)N(d$@ zC&x-qaZ}=Cy}quZ-$)jb=Q;}4j~)27z!Wf)<!`^Y&$}!41X&#ERv1~ZV5ZeSX-3ao z&MOG=NTXk$jxA=&8kN4S<cB2fjV*K%cz}Ad{(MH_?S67RGw}gOenLhy?Yn&%qdL@1 zmO>#NoLgspe;54DuS2=Np2OGz_4#;vkEGfn7~bPw9r>7UpQs2lYr31|XO$S6o2}7m zzSUH5$>z-OV5|Td8K8{Wd5$vwxkFFm_faf?DGPF-cqy;8Y;0+3nDBLD&+d+qSnQQF z(}rEEI@@p`-zP1E))Ic4%)Q<<^^u$jz6@ry)VOA7g^lw|KR%qH>WSrHL&Eyxm8ZO0 z5AMMaABxFTIvHI$bo*fB_M|THjrnrS*h9PUIl@<#$CPFmXU>NfEUjq>mXvQHLvmuR z%WK6HPp@Ub3Vdw{1{AfIn<{Js!&fyw`0|HHd#kia#y{eHjg-*s@13Z(`y91_vWi>$ zo|(2N-#87Ylp8%5_k2f?QV505u1q#Xk+C_eCpxZl=PSq%Oe!q)E#;@uo>X&csH6ms z9N*j$d9U$#_87mi_ZGf3g(Qdx2K()B96YJqSCxoin&Vihmd>VYS>MSFv<YW8e&?bP zp_rxP-^^Yz!u>=Gzs0<iDeSiYxaIoGJU$#{R!K+hxVh9h_{Q8DkACIrww_-ND;Gyz ze<|C~&(?3yw4x<6rI`qZJIW^tJxzVAuwO%54k}wKP7)g5JqG&q^&Px^kf1!Hw5)DN zs>;^*GP_fwPg%L(y-}+O-+#z**;#qRTq=KGo<g1$>1;`pe>F0LlH~fCtY@KZIcv)c z>3)$dKDzD7&Kb|kJ*7zQX?yO~kO2jYFT1UQG7y-4CB0%}k-UaT@9^+&+MohEMTN+y zH66j-+%RmLPPsYL=y8PPxH)}Jzsow8mnNJ9c37X>hqW=!wGKQ3&Z=J@ddut3#GS!} z`I#B!l<J~zg?OHbGgNYp92xcEe10{MkEmr&tn<6i`Uj3owDy3d>(^GypvFm8iE3fn z(q%;ozLeRf{Q~*z0Ul$8WCj*l{XYp~^ECY{Zl23--tG-IX7Vy8<$-a+!xbU((RP7z zzc(m`7^G#PGod%88ffZh+qb_5@&(j4%4aaAz==JBbOf@P<>f(3T_*n)j`5O<+er%h zsiVW04P=i?Z4x%+^&p1G&Bv`B%zgY7817lA-9zAIaP#2q+mAFiaHM|ksup1n3V8!$ z4P1;#E<19V#RnmM(pd`VY!)GRGwjCHG^dBf7jONR>w$UvI7(How3(`nf+agMiZYRp zJB8VPko0n!=~s^YIKvxcVQ`h>*JQt!^e<QDmKWsBO4%S!-)&!_kncaieLx35xiic1 zxQOE!FU63-Qx=ZrSHEEH->->}E{g7ZO0#-H*0JCCJo3Q1Zuv=_p`L^Z<Iu85KHCYV zUZ($X)xhy+?Hk*MaK)?=OI_H*iYy;?mLbD;|J47A7YWG?duy}v>jh=LbYzzGVzgb5 z)KJ@sftd#X<2P3qbtv?^kiatH9XHIkK<2O$gKqZq<zh6SE>bVK-5f($3TghoUA1(N zFJOOlEPtydr59PA!kt;#<e!|dsY@Y$)v=!NUR4?z@|1Uo!fsYvG2CDIlg^tBG==`z zb*rN@Q?hS1z6LskGnA-*Dzh=~H-@a2+)t;^!)W$vWEoOgZNxRF8dUbZ{V&|eGi^3} z3CqiYD+_PEX%Id*y4IA*9qxmNmC`&tIXZ62Rn_(*#kX|FG(YK3fBX>W6ttDOC4PH* zWlVJY<9b5oTLs@!_}xN}A?ZC_niG9&kM6nsubD_q2mAi1(>!{WYIm>LH}4Fq1q@R- zJBhCKsaHH$9-jZUR<9f3Z+{Z-QZLjl<qx0tVpunrHm53D9qGlIFGaOGkK=H4)^#?4 zSB4Ir&>z}|6ADUZ)f;SX^chyxJluVNU9YdpoBsf<id$Wb*Z5yL)f+xrbaiSXJ!Vqo zYL8}tVZwu^HMQM*5LH3<H;tvULx1cdUGGb_W2YWa7sr4)|H~*eQGn@Y2|4!@3;geo zfhljS=m`8*_lK9PY^9)djn*<g&`d15kwp8^{<5p9wcP0DZ$Lsn=l;es;|7&A_b$*8 zVlTC)5Ty0#E4jQ|YmMM*4=a7llj$E^-O8en*V?j5T6oOMqDE74f9mY|YSK5ydj1)v znJ<-FWb5rWSD&E+k^%|SagQQ|n?#Ref=+sm8`ahDkj_2K!L)a7EK+|wf8U^T?Q=Ew zB|1O>ll{6(N={-qU>M@;KyNvs8MmOox%mXYg9F3KoYdZvOZn#Keb2g%`<*?Q2s9i8 zk<dVsOH;U2qoPY`@eD(qd$k(vWmInC%wxoN-QtDE<DXCJ?89Yc_;K`cLX;MR?91nS zTv!Y%$(!!zRB}JmqTsh3ER#x0_RP3i?SDIpe3#+toYPp9w&f0OEAy{sx*xcj*v4W? zqNtD{L@L~O`M_WUb5o|RI>uUQhZBM+YOd`0S>E>u*zE%vn8{9~u0-_j)SIN0**L%Y z6s1nzpv;t}sv9A!L`V1`Rc&+G&$3^@c31E6$FSjNj|8d0EL``~0|!Fi>%B0An+UUz zdue#v3P^h}E!j=ZRIS_p85rgRQ<zhp`p>W7v(^*rUJ$>+{S&W52y@G)xoG!)2MNlJ z*HySpqB!-*U6db_#VS9pxy-zu^`I-$Xu!@?*a2~hs~YLqVxv&n2ThpNz3A+gpyF-I z6`8P%|EAB-;asq04STT5{>wO-y~&GXVj?jr=b3D{UvY}SV!PFJagEb_bYMy-oQ^<s zb>oSf{nl1w^-up9$^rg6ppcNI<;T7CGHgE#36qWOst(j=NMU_cNwX6nv!AqmV-2nH z0ZDDg?8t{>R(|6+B%9#PQOV&bXj3Hc`JIr#)q0AR-eTSW@3tnB!mW1UjRh7crN#KM zYNBR#iVmIJl7+fIN<&7$I7&Ie-3*0V=1(aYP6<qTy8x7l87ZJ{yjndyyZ-jTnccwz zX^=hSc-cDN*DkVF(4bN>=1KKDV8vjXzwPmu?2z89gM|tB@8~PzL|&CUAyxA>bYF^I zB<ZtIruthNU0o@Vv8<te@U?@ZUM%6)S-z0I7OAPba!Xt_i`fMd#py2YScx<X2ebyz zq<AesgPFZuj@pSU*|1XbUgxi6+QpIn6tn%Er}jQaH4(#Yb7D(bWyK>=J{)n5q@k8k zkEfyA&N|D=DDv?m+m<J;d^pbhmVn*$LQ!CFlNtjR%l<E)F~_#w=W2c{IaSq488i8d zHO301WrSrdrzg*OZifTANuM4|7>0Vt(6?*N#=mz*iZ$K`sr+1Zb+w;t#`q^epX(jF zilpP*DRkxC7$}oPI30n8qgNvG^(_Too-fbZqB@#t39p4hxGFh@^jQ2b##VG4)$aZW zT8HK)NC`~Qn>)t$)!b(iNr!(Np+=pn{ZxLbyeu&JZKE+tBR+s;KqhB7sa)k`z%8H< zr<dS)T)8n9UCjE0?OA`Xtp9CL#C`bXJ>ey|Mn|`ojlD(PB)l+{i46EM*6wQBKXvc^ zyYEXQ8XQG8=z?i}ZJD|9<qlD-Qc#FrrJUJPlmF?p+BEy_K3XZf+cHM!K0mDwx;^Xm z_8}#;->r7v$+S6>E%FEQvaQTvi&58WjKVs$sOxUe8e1yKJF<yx;1fys?dCzqI8@Z^ zu7Z4tazX^>cXiuFv1{HNQ|aruW7!cw7btKw0yy1M?uLan+|QP!$B)@`ch|`0M<Rq9 zO;kS3f<gyx)erp#u!XA9#`(rg)pDBzk5axX5vA{;{AOI48taBk$o=tYsPIfeFxeq= zsj)23;7;A7msUc6rrK^<VnIRKv~NSEE4@hlTZRqi9NVj3WMneJZmoI^C|v!L^5WPd zGDL@sY`V&RWQh8sHr{8^V@!{heTFNuCt?thKXCYDrQ0jlhgo|hB+Uk-;v3t8+BDU| z#9GT1$L<nl_B<nsr_bta!pjUQVbN0KqahJt+ZkqP!6F;$DQN$KFjGXYCR4(R)<SgQ zHP2)87{>i>pC~@pRI1T3yH^@$!qmQA<uT15oSy2U)|&Fqa+K$4l<<ni&$l-2R>>t) z?P4487DE%+K37>5Yt(+4pEpEK)Ks!l`|-8+Z)0k-=MwJAClp}pBQ1WI&^X<~)l2jw zgdV!=XA51eMT+(?o9zd!-Dw8dp3*#BP;*q`((V-B8ZGBkfs9WP7u@1&gTnsVw-phs zU6~E!9!(pK$A5;I`<|10)EY(t8SS@@CI^cdru2GYyE!T&MbSHtOU~R&05yF=E5i}b z40mRae+~)vL&^^kEJ>$fFum-X7bp<wDtl)p%+$mr^&5@WMZ}FBdc|FT^~9X_O*^^E zilavpfyr+qrj<8>$_VruXb^OgoIzzaZbfyL?wi6pZMy<(Ckl^NSocv;mkVzX8d5v4 z5iyqOPT`-NH9lohHww4^<;Agn<<3ixWjTA=XTN<MHO;_y-Pd@R3r4EP4vvn8dUcLL zl3#w6uxmHb8&M;xpcK<@50P<!Yz2F_-II$`^4Um5n(%?*^RviXfEG^uB?VX3NEC8f z$rAUQj|V9#u6d9G>lPPs8x*})C2XsO7V7pmI!<vXhneoX$F}Rqn#?X=A5r~OTNa_P zf7)B4Uj8OCd%~L9C*<y=mQUUP!`^$pHI;5*!*j-pqNpIfh#;ucNR>K*fT1eVs}SkE zHv^*-l>nhg5eN)jK!|kdN()L2y+;VrA@mlKd{3M?bKdX$8{X@h%O6Iw_uA`O^<MYd zJ26b)ZWbHN`ESo3`3<qp+205<>yi7l{)G`Yv`)&~qJ(x(yPolNsA1=!^yN*CbOt$a zt=ly>2~9I5^wUF{Ugs`PJfnoX<$4M}eV#VJ6-{{`CJeO8-8ad*Yb1wTF>rGZX%92G za9poc=NiR~)c73go-W7J!`M-6rw`d~j*gwws-|ZNJ)~sVMt>qnU327icEl?1x9A<% zx>b#QBB`86-{YqH;w6GMmB2_N(B?GL%=eA|HfUfD@_z+^`gg~wEbt*?WPUz*FXa#k zt+)2~3UFxgi)pGJaB*r&JwlD@4%k5E$q`{0ZzMCJJ5^s(G7@LOQQR`WpM{w9IsDQl z{3?KZewQBg1Tm?5mC{UaTews+yeBXgJcsEIDBa@cNLgKfm3H67E2y+=boj>p+W>IR z`x9ZN=hLVqCH2WV#&jsL?&rA4<^vxgpnIN;gf4Y3C;x53a69bGsk$2bWN|LWVgp=U z{U#ua&15DXwkzK2N$X;|*7S6q-0y9CI)JdCw#YP+jhy3e>27zS4;D;ipj;+h5#30$ zeFNJ%p&zU~9}`DWU&?+%-0*$^3SSG{4J|fqGUD1VnJwAIn~pV>9`Kv9^BWeL3dW=m zn*?;ygBC|G=KP>Ix3K?N5d4=bmOVhCuK3(9+3|n1DMpg*TcTCC7W2$uQG4&g1a4Zf z@o*vbX|CC^5of60=LX7=;Ph@(TD!HC;I4>v3UG<@Tg~P*!l4Rkg5{W8L~nneEYPy4 zsi|VhCW@P&_{i@TN9HE1Ofk~Z`;%KYUXF=T03J?$U!!ZrU`5BjQCj!<p1+o&^eko~ zU|{GA3r&^YJY4<QEs9x6`!hU+qWFCfc%L1=W|auqj8e_wDf{6wA9;1#8%9$lDp_Tp zd5T*b%_D&c&Io`EUBmni$w+lq;dTBuY>;gKt8zug)#fg1?4uUVhbM{}gVsjR37MOy zzYsa!>f1_uF8|TVL=|5REAW|~uuda?)g_WKT=`2%e(-!UA7(Ir3DV+WeiAg**6_52 z>1(XoNy_ots}l{MTpOjU8+ok)<HT8EO<ZY@iIw-Y-}oWI##KMiEf$7fT~(l|(8+L& zdSMa&_#(^;G&!P}kc`LCSMiD<8g4hhQ)`}(ct}I5e+p(_9%qM@+h^YJsP=ea^xv@I z=Hyho-uMow^`Xq@ifM?UEC0+hvdpaPgI>jVrFHIK<UKWR67U0RkhT{OTXf##JB52# zinX#8A3J%aGJb`S_CU1z9P(ZmG?&TO0&gxXTy$s>oy$xXZM<=Ca4S)@sEmI|GPr8z zd5~*&d(Aalu9z<VpUdHKljAfM(MBa`R_!P!-l>+csciUVn!yYAr-Wzo=Te;D98AY` z7A;jtvC(mezs;NE`j4(FQzYGnoQY~QVpm<%ajq+AC%5;}N3vHbT0S}`>HE_R80Zmc zK<#R`@}7QJ7vG7Ic)i<nVB>RtdWe)tv%-UhMLusxn0(adJVjPY2(bQ`<fns`SF0&o zVJl}yQcV(*d7w<(p)eiowT$iS(^SwkyY5{*0y;mj1G)JVe2;_NQB(dLR68u{?8rn= z3&D>goCla8WXP<EMrTKg;y-5H{a>?&2#(=8UzLega|FH2Az|}}g~B_mvg9RZ5jVXH znDk-7!BXbe)z%F2({8>wIHHCS6%kL#(@_p{`d<XtgUnxKTdgR@h(G8a!C_|{Mrbbg zDavTEK~rY*h}?zZs!;;B%=V5C1A`ky=b{?Fn0BT3JxaN&U5xho6o5x|7@oJnDxC6~ zI!qNyzS)7}pVAapY?>)Tg*kx^iCUxcKT3CD=lO4_Ls)$cR%eXL*M9V&%%5zxYWwq3 z|BMI_)wNh)rH{w_y2_aH>e5elv+jlu{r2KTrIF1B(q~JPW~1A8RLI9ZcNS_B2p$QG z=sd*Dg>MOx1n5q<j|3g!CbFZZxcC#vsYtpz1Ro;)UXn@fU=$>kYSJ@Mg$jQ|vsu0H zgMLt@ihCxFbHJBNe~BVPb3a)L&KMA){kfyF_3!FU!Og5v41?>z6E7+@iOe!}fSxUW z#FQ~g_4X8JhA4fW1Ek?w1Ai7Mbnb0PS-h~~TX67M^1K$9T~boQ1s(M9dLALoh<OD1 zU_!l;Ka|FjHb6lv3o|!gFl<@)ma-eRavksgLf7$QWUGH~H$^zgh4Mo7J){%8)j0e% z=)v_+3F4C@eV(@QR%8cPH2M>KH5(;Ijyn46VMsR@B4aM0ny#uM3s>afX65NnIWbx? z$Z_7O3|w7!<MCyWK2`m5M@rB?Hd5???XBk0OtF3w(7z|Q(5_%<g4NCtaXcD3LQa9l zvh8|>J%6#UTOg{y;R%hoo|0dr)LRN_BhrfN#I=P9<VftIz<{@lX#S{;KlRC(Ec~tT zhybmG&35-G3yCbuM7<y3Am8C><J5`^e@6h=>FJ1L*N7JBRJ;6?;D@q}zCtvZA6an{ za;B8#4lrA(Gpy@CKWkrU-gDu2Psmpxj?-Y7A&gD-0!N&Wcf}txGtn39O^aSDg?N7Y z6;8_Pf3;NcppWS3xH*0};^u7H_&}%8Po|HenhHd0zp@?UGw%v9&s0xtzfy6GP=~ao z9UJPT>K#yA;d!%Jv(ltES`We0sgJJ4dRtPC9oS=ZJ5003OPsY)aXmHlnC7+3+!)!@ z(=oRvPz^V1sGV<NpCBnxYAO=rl8FM{g=G!-P|Qkjg8x|>;oCyVmBlhS*Tx@s$*B4* zA6H?OD8){9R*erG%>M)vxXrKn|2arGl8mKk&$0Gl>u!mUVc7YlI-C1~Yklg6z!T9l z(|3*wFRW!Fyf|vv_ZP2U3lz*~zKkCmUWhA=<X+f7!37VcGew`eSv@KnIFy~lgT1gC z5#9}^K~P>3)50=tQ`2S|z3r9G#bKz+@>0-3UB@bc)nNvai@oqm+=}F3Q?&3x>7Kd8 z%A+30!QZvgzJ6Rbib7Tg9xaLUTj!bkXol79&2%H)(6p;Lom8o6^m!tfYwtRZ1fy0F zVnwg!{M`uu`fE)RE&4T>qR8sJXH5w6M@XgerEqe}>lH>gswv<KWplmvg0(hN-49** zVMy{u<QTw!yp))f$5xDlkMEpc*x#U0WYj9PsBw;f9b#!D&PN>>P^Bg&L18yj^|_h} zKNE!4iqZVh2Ip<C3TM;UP2Fmb_cx}4(rAn0!W^P%YyQqJ>7Wz+ySX)qAu-|juG!w4 zqXeWfK4^HNRMXJ{9}P3V;E8K$@uq3J8@MGmM^aJpi#Q_x^fo+wKO~6@HC^AV)LZj0 zNFX%57<pU7JMKfkV?EOIX=Rq3d1%_`NJ*NND`sZqqYl)iFa?9oBfhsM7CBeztrZti z{uC2YGOk2EAZC8g7eF2n>;Dn0@^4$s{JZ@>O5_zfx7tg;^0VN5*!wr_Th$IGw2%<# zSyOI3E-p1^pS_<NTW1Z;ztu7?RBo*sEU5IB=tLZ-HN3AWa6%}M`KGTwXsF@ye$qyI zO)ZgT(tsnbP5P|1Uv2J8%-7&SyWMKH2{f+Dd^@^4UEZUcM;xK*OjXj9KU%RWah>ho zz`F<l1m3p1%XhXO*+Wxf+KY$fzZ=_UW<G}LBY0fYEk)OF(cqY^iV#KDdz?7CF<S9T z003_a6L=LchU!OUrH$~f5_uL^npzBX4uRVq2Vx9sWCfq={jj!>y;?1kgb2PA4qJ-@ zXWLhE94v99O>)$-WFB2ln7fC{*s#0V3{xkp8cW+E%pWGWGp@__pLp&WtcGq;o<-Dr z0%L-ve=@``L8(9$w4%&NvdK|!(jrBa9=ovaU~zg&A+tZa%-&LJHYsu{GmZhoy^GgC zU(t9gOSbhbg=f(G>ipE<Ln{k*9w|*fmDrtj8gqt#89sA{2dTq~Z!}2{&$|Q{yH3;I z2TQDH`R@p8)uGtDC^OD=3~R-ip!2%gn+-pAOe8v2OBxaSx;7b;0PggUx5UT-;Ne>K zhp?pFaU(%oVinBF*%bAI3-uUQ_J=|PnA1QCW)uS%w}YXek0-g_3h#LHWEb7s{S%<? zV(D%08`Ianvdf79Q5)p$fRpXTX;O<{%yRbmxt<2s(=H0}3(>sYHz3s`HBG5Z@WwmS zz0sosA~rjD_Vpth$X{B+of&s75k2?RjYbwK=@u3IkJkLC$NP`g{v^4N#HdQYJ&6uu zEjGDf94n%|qq~u|8O^I|Iq?EVF!6bFZ%n9Ncuk6iNNMvn)CAGK_D<li|H3ThTHS{* zk%-Zq1Q3KeJle%w!VcRNT&K@;9Hit<+&`|<tTR84vE4)Fp>i@Q>d7is2D0Ib4U8L^ zS|gWt4h>lrl*$ACSGdBkGrvvF6n()PQjxNx+@t5~_PHis=xuLKq^B*YTp=XVG>S5I zTM+y-DNiYJFxF~PZP=Yx2^}|UJX0gm2_Skr!x5lMz5P8_K5jpGy`O~1SH@UqE9pE; z;3_edY~6D23uEQoHk~lE8~EAce@V~qfWS^-XdL6=7MeIvwxq-Zxd=kIPEi1AvlY+q z&=*NTZA^pzuDj`pFC0{YXmZ`Z1lb1*L3h4QV9z7g84*8*nwhZ+Is*;o=b{g>OClrA z#26WM#U;u~Zn>y-m_oX!3g~-%$XNf5AniJVSFm*oueV*wqJf|O*js-~?WOFLNt_N- zJMZqp-SHLK;kD+k(<?3^xkl!He%e8Hg4KE;Y)UJJPqScY@xpRB6%sz@Qu=Pe2>}s) zVHoc`!3_T!>yYjhng~*&qSC3btHj}tT%fmXyyln<zUZ(`(|Bcuy|-__@h^%h6EAEq z@o<%(y<C*5N`zlsE?~CcQcUbux%C3Vo@&RpYb0Li`ebm-UR;Jh>uhv@f3WTbEvBt! z(42>6kY(Yo!vgp7PFT*$0JBuI(89I^%f?i>1FXCFpPmn#BRzE}G{nBzQMR{@?Ur-v z1(EC`p_M++)p^H!yupw`gib@<i{~JlYt=3jmDZ24N=H7Tx}YI2e(#E%=Y<mc(|14( zWQACKn|ABOC<=eqVe~waKzGftpLx+d!IK}PkU3a1+T{r}s`m<Ie7T6Z1?Yujma?$A zaY!2=Jf8nAvbF`f(Em!LTHO3s`_SaWt&^@5TbsvMgw4FSJ2o4fX9TwW)pS$Y@NiQ} zkylcsulc;~m={L}K#VvkrkQ3r_O}LSN7}z-ZBeruTI=F7S%rFIc>U^Y8`chh9m#6x zbrSb!B>dkawXYD{m%+`;hYNCSxyc@XOBT9_FiTG`v&0~ae!ES+fdLD+PHo0Zzo(CX zgdA7=oubx23lzpsG&-hmRK?qaRM}}aR%W&0PCq7L5W;m!`3@$UN`2A4ucVDv8g}n7 zD#koA@hYqlTv?%+rkTt9B8{;4nF?Ezp~10uy21yVBAE}m5wiIXJZ<R69|j@j7JS<z zO;kWY(7}ca3CZ-aKuY~H0Ftx8S;oA=j3^Pf5jXo*;6>N1%~AlIYx{33+efGb>HHd9 z%7Q+(MB&=^Y+_3oE8<s|Sb{TpfkthLVfPuwok2~}3w7a}$avQi$sDa}skzkqsW>xr zBl3pDV$Fq|H2ms}Bpqf9X~)_zcVuAM_l(jgn`Q7jetq88th*H;fKF{I^REKhNQ2%_ z7_y|A>=&0?mvZ)qH@IaeMOWYrkm)L)=Sscr_Wvgvn05Xm+eZ%mA&o~~RIt<wYdUqs zZAFn`4O!ic>N)%J#R9qawo7JW4`>R-fQ{u~KP*{({8l@duy^6U;_Yb{hK2o`!J4E% z4W9;(%4Z)gV`-}H#Rop=#+%YNNm%=MewEuFE?myOt>pFs+v|mdR#Z1hamy-msg0Uf zwWgC@fK*znuzw=#8a-k^<JZJy-$+{VolkCI4!xsbWVTv9uqR@8SjO9?b3U_No|!~^ zOC{-HqdrT6!!&P}?1PiyyyBb8irgai`DSI672Tl8Y~daud{0H64D<CcRevNIvIY>o zUs0D4nl*)KyQQVHi!R8Yqy)Nz=D(@mQjy&<MgJUELj{YIb$5r4;R(!(x2815bN_V( zg)(~r4RuE6hz#H9{>TFYzvg^|TeNtNcss6xu)$AuF^T9bvI1&1Me<eIRAgt>>^ z<2HlU=R5k3^zq-0vX)EFdp6z9l2z_ahWfF+E>jd86gAkZ(;8GA3yF618k6cE39u+Z zXv}G!23aUEJ!ojwT$(%Ij8&0sZVpbZREp_))Y%)iqdedu(Dr_H^_jyAGs)-|v?U!O z_)q+rfI;eAN8(hC{1r1F)9br{;Og0=0|I$w$UAB!-E|_Jo*A@?tK6T@mB!kOAHS^> zdNqZB%lTb9K6C_*df(p}lyCT@g=JU#^9y{AL^^$TIuZ2`iREClS!{b=#T!D`cJc=R zHdcQS>FcCh+`O^cYl@E&Ko*8`H4P%(Y#__b$~I~_27;B9z@RNU4*gHhZ}m?w(L0N< z!xJgx>u=6%m4l+!C340$+Fwj3Y_L+|Sf)4<(^qZDGp3sUKIB1uPw`;GyFvOo`ZmRe zjr{bm4TkXL`oU?{*~8QTAG?XlRJM_@w_Hq|_jDECl`++G$?S+8go`bzber<OaB4VP z)I8zm8y;fq=8Ww{BR^O;`5+eFY-NR+u^v176k{$xY%|#O1{xs8|1>{}|JCF7A8jtU zS5y5WyhBEEA$xVkEQ0$_(H)v#R+OaT9D<Bhq0AmpMyeCi|12nOUO}!T*?`=n-m4Xk z-(sVgF7&SP7_&rvV~A2o7%?2u`H<MQN;t!!N@ET;Y&hR>+#9xb+T7U_8yrY-mThY? zR1&@fCwteqg-a_Y#Dc~TwhQ@?-S}5Fn65NfL^7=3@}Sient09Upgu5Xw7C&mm3x(O zD@60d+kr}E&kX-6*mi(zYL!y@6D8L!v<3h*+2#C9rgLd8{5SyNct9VrlfG1?!ZoVl zmuA1>b3G-EpkA-)KmBp2WX9L}#P8c<6D!V)wAl8oI$_T&^^U;NU-AK^Dcs#o%nCD= zS+Mcb1ssz_-l>NU6U<(2)JX<IyFwM1h&rh2iWzIL!m#OqdG^}R$P!wJznb43q%3It ztZ*2);L)qu>2ea{a|So^Mr@0W*Uxk?_|8Hz{noL$AQLpo!(jwk3_fV!*O?x9*iTf} zWh;0EHHVo%*+bN>2bTExB807RWgFS3uvJ=f=jY%gV?Ja$yq+S<aVN(#QG^^SCH9IA z90vat%L7=N?!dcTTcbC9-vS4QhUQ`yH7I9}aP-H&$@!GjsRT7#O;7m*Xe~Dl<LpWg z_~sw@m+o0g?W^^oW_%GZLio)=LqO47(#Gmw1>DgWI!KuJuYj&0F}20FhQ3?V4s);< zy{hQJ$A$@%MmFZ4Rgpk8_`6Q8g=wXUC2Pwa%IkIiCM?fv;MWFr3E_gX$X0sKkC1gH zIQ#p@jaH>i^`UC3tFNNo8qawQ0*2OPMkS9y+&Rpb|2Undgsgq`RSw|Qf;vWo&zA{$ zM?ax$5X|bxhWcE4s;9*Dr=?<Ta5YDV*8`=ERy5*dk9Q;O)45JB710RoX0%BbQY5$j zrfLoreaqWUdIW)64b)$ou0II6cL@fOD#&%<8QzM0Or>(F&pjux-Y2*UX7Od;AiAd} zdG=dATgvHN|9M*>BPsUW4RXyu?)AB5Iqm~1E{4X@`&+?xsgd?n>5mCUFHZ=B?$BGA zX=w$$!YOreFvueR85r5zq>gE36nX^!TeL)?w}uWM7GwxtnI0QLLUd#0Z?8w*z$rdj za%pQ;&v1-3lF}YKwMoQjCK%isJ@>*n7I*zfn4H&HwTD^F2Nbzx(3*ef$m~aDXQB(b zqFX-WGVY|jkzC9Nd=f9eN4Kez)I5(Ca(sG_RLg!J^h23+mf|l1+@TL-Yd#J?e((E+ z*d8W#UWchRTF0g@Ltg69n9Hu|8gZ@d*uKR#LLt(O<4BjCi%tWSznDt{(;Zf82j9e_ z+II}CGcDp50HnN<F@%C6O~I`u{L|fWe#Eu<td(4OptYWY!3GIy{R1(aA@3$-akQ^e zIlcK&XPJM~uqBU(N;*7~f!dZo4K_br79s$2_tJ0JTc6qpxMn;)s5X}76z*lvY*TRA zyK}AX@Szg*aaMj`oW^*~HR@-+5-Gh)E4|gM383}_MU9=COKv!L#7?n65%(s3h2}n^ zi^by_*VocP*UBT0Mvr`)hMD`9{Xl~zK+QB60gAY5zzp&&B*<yNdhK_(9A?gA+IX(1 zgS+S&N_$YA_kK+aR8op=e@oH=bE9pz!<+)7*)iOocwrg3w7TywW1?iRL#{e0stV}n zXN13Nl9-mi2I|bGCzsF8!>yT+povML>-nXvM}v}=HKeIeV4lS+E5QE)WXK?T$D0#o zu?r<vorrTbCxUx%d$py(TJ<-%+6#=1RX9g`DU1(X`?OP0P(uLzgK9Q|D-)Dopa9ZZ z%0A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 J40sEG@;^hlltKUi literal 0 HcmV?d00001 diff --git a/073-AIWithConfluentOnAzure/Coach/README.md b/073-AIWithConfluentOnAzure/Coach/README.md new file mode 100644 index 0000000000..aa8938734d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/README.md @@ -0,0 +1,79 @@ +# What The Hack - AIWithConfluentOnAzure - Coach Guide + +## Introduction + +Welcome to the coach's guide for the AIWithConfluentOnAzure What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. + +This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. + +**NOTE:** If you are a Hackathon participant, this is the answer guide. Don't cheat yourself by looking at these during the hack! Go learn something. :) + +## Coach's Guides + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** + - Prepare your workstation to work with Azure. +- Challenge 01: **[Title of Challenge](./Solution-01.md)** + - Description of challenge +- Challenge 02: **[Title of Challenge](./Solution-02.md)** + - Description of challenge +- Challenge 03: **[Title of Challenge](./Solution-03.md)** + - Description of challenge +- Challenge 04: **[Title of Challenge](./Solution-04.md)** + - Description of challenge +- Challenge 05: **[Title of Challenge](./Solution-05.md)** + - Description of challenge + +## Coach Prerequisites + +This hack has pre-reqs that a coach is responsible for understanding and/or setting up BEFORE hosting an event. Please review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for information on how to host a hack event. + +The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. + +### Student Resources + +Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. + +Always refer students to the [What The Hack website](https://aka.ms/wth) for the student guide: [https://aka.ms/wth](https://aka.ms/wth) + +**NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. + +### Additional Coach Prerequisites (Optional) + +_Please list any additional pre-event setup steps a coach would be required to set up such as, creating or hosting a shared dataset, or deploying a lab environment._ + +## Azure Requirements + +This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. + +_Please list Azure subscription requirements._ + +_For example:_ + +- Azure resources that will be consumed by a student implementing the hack's challenges +- Azure permissions required by a student to complete the hack's challenges. + +## Suggested Hack Agenda (Optional) + +_This section is optional. You may wish to provide an estimate of how long each challenge should take for an average squad of students to complete and/or a proposal of how many challenges a coach should structure each session for a multi-session hack event. For example:_ + +- Sample Day 1 + - Challenge 1 (1 hour) + - Challenge 2 (30 mins) + - Challenge 3 (2 hours) +- Sample Day 2 + - Challenge 4 (45 mins) + - Challenge 5 (1 hour) + - Challenge 6 (45 mins) + +## Repository Contents + +_The default files & folders are listed below. You may add to this if you want to specify what is in additional sub-folders you may add._ + +- `./Coach` + - Coach's Guide and related files +- `./Coach/Solutions` + - Solution files with completed example answers to a challenge +- `./Student` + - Student's Challenge Guide +- `./Student/Resources` + - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-00.md b/073-AIWithConfluentOnAzure/Coach/Solution-00.md new file mode 100644 index 0000000000..8ca1a44d71 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solution-00.md @@ -0,0 +1,20 @@ +# Challenge 00 - <Title of Challenge> - Coach's Guide + +**[Home](./README.md)** - [Next Solution >](./Solution-01.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-01.md b/073-AIWithConfluentOnAzure/Coach/Solution-01.md new file mode 100644 index 0000000000..01d1e30c27 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solution-01.md @@ -0,0 +1,20 @@ +# Challenge 01 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-02.md b/073-AIWithConfluentOnAzure/Coach/Solution-02.md new file mode 100644 index 0000000000..1ef8ca5035 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solution-02.md @@ -0,0 +1,20 @@ +# Challenge 02 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-03.md b/073-AIWithConfluentOnAzure/Coach/Solution-03.md new file mode 100644 index 0000000000..9591196509 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solution-03.md @@ -0,0 +1,20 @@ +# Challenge 03 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-04.md b/073-AIWithConfluentOnAzure/Coach/Solution-04.md new file mode 100644 index 0000000000..90a770fdb3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solution-04.md @@ -0,0 +1,20 @@ +# Challenge 04 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-05.md b/073-AIWithConfluentOnAzure/Coach/Solution-05.md new file mode 100644 index 0000000000..c320bf9745 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solution-05.md @@ -0,0 +1,20 @@ +# Challenge 05 - <Title of Challenge> - Coach's Guide + +[< Previous Solution](./Solution-04.md) - **[Home](./README.md)** + +## Notes & Guidance + +This is the only section you need to include. + +Use general non-bulleted text for the beginning of a solution area for this challenge + +- Then move into bullets + - And sub-bullets and even + - sub-sub-bullets + +Break things apart with more than one bullet list + +- Like this +- One +- Right +- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep b/073-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md new file mode 100644 index 0000000000..04e22a4519 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md @@ -0,0 +1,33 @@ + +## Data Pipeline Overview + +The goal of the pipeline is to ensure that +- the data from the source datastores (Cosmos and Blob store) flows into Kafka topics +- the data from the topics are joined and merged into transient tables +- the data from the transient tables to finalized into the summary topics and tables +- the data from the summary tables and pushed out to Azure AI search for the AI agent to use via MCP + +### Steps to Follow + +You will need to run each DDL statement first to set up the Flink Tables. + +Note that each Flink table also maps to a Kafka Topic in Confluent cloud. You can browse these topics as well to see the raw data in the topics. + +You will then need to run the DML statements to pull data from various topics/tables and push them to the final tables that will go out to Azure AI Search via the sink connectors. + +### Location of SQL Statements + +The DDL statements are in this folder. Run them one at a time in the Flink SQL Workspace in Confluent Cloud. + +It would be nice to run these from the Confluent CLI. + +The DML statements that pull from single or multiple sources/topics into the final topics/tables are also available in this folder + +### AI Search Sink Configuration + +Make sure that the topics in the AI Search Sink connector matches the corresponding final topic/table. + +Make sure that the AI Search index name is also correct. The MCP service depends on this correctness to fetch the correct data. + + + diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql new file mode 100644 index 0000000000..f6ea244cb5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql @@ -0,0 +1,50 @@ + + +CREATE TABLE `product_inventory_depot` ( + `key` STRING NOT NULL, + `department` STRING NOT NULL, + `description` STRING NOT NULL, + `inventory_level` DOUBLE NOT NULL, + `name` STRING NOT NULL, + `sku_id` STRING NOT NULL, + `unit_price` DOUBLE NOT NULL, + PRIMARY KEY (`key`) NOT ENFORCED +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'upsert', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + + +CREATE TABLE `net_sales_depot` ( + `key` STRING NOT NULL, + `department` STRING NOT NULL COMMENT 'Department of the Product', + `name` STRING NOT NULL COMMENT 'Name of the Product', + `net_sales` DOUBLE NOT NULL COMMENT 'Net sales amount for the transaction.', + `sku_id` STRING NOT NULL COMMENT 'Unique identifier for the stock keeping unit (SKU).', + PRIMARY KEY (`key`) NOT ENFORCED +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'upsert', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql new file mode 100644 index 0000000000..3bffd6ff6f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql @@ -0,0 +1,97 @@ +--- Set State TTL +SET 'sql.state-ttl' = '2 d'; + +INSERT INTO `departments_flat` +SELECT `department` AS `row_key`, `department`, `description` FROM `departments`; + + +INSERT INTO `purchases_flat` +SELECT + CAST(CAST(i.sku_id AS STRING) AS VARBINARY(2147483647)) AS key_column, + p.customer_id, + i.discounts, + p.receipt_id, + i.sku_id, + p.transaction_date, + i.unit_price, + i.units +FROM `purchases` AS p +CROSS JOIN UNNEST(p.items) AS i (discounts, sku_id, unit_price, units); + +INSERT INTO `returns_flat` +SELECT + CAST(CAST(i.sku_id AS STRING) AS VARBINARY(2147483647)) AS key_column, + r.customer_id, + r.receipt_id, + i.sku_id, + r.transaction_date, + i.unit_price, + i.units +FROM `returns` AS r +CROSS JOIN UNNEST(r.items) AS i (sku_id, unit_price, units); + +INSERT INTO `replenishments_flat` +SELECT + CAST(CAST(r.sku_id AS STRING) AS VARBINARY(2147483647)) AS key_column, + r.replenishment_id, + r.sku_id, + r.transaction_date, + r.units, + r.vendor_id +FROM `replenishments` AS r; + +--- Available Units Computed from Cummulative replenishments, purchases and returns +INSERT INTO `product_inventory_depot` +SELECT + ps.sku_id AS key_column, + ps.department, + ps.description, + -- Available Units = Cummulative (Replenishments + Returns) - Purchases + (IFNULL(SUM(rp.units), 0.00) + IFNULL(SUM(rt.units),0.00) - IFNULL(SUM(pc.units),0.00)) AS inventory_level, + ps.name, + ps.sku_id, + pp.unit_price +FROM product_skus AS ps +INNER JOIN product_pricing AS pp + ON ps.sku_id = pp.sku_id +INNER JOIN departments AS d + ON ps.department = d.department +LEFT JOIN purchases_flat AS pc + ON ps.sku_id = pc.sku_id +LEFT JOIN replenishments_flat AS rp + ON ps.sku_id = rp.sku_id +LEFT JOIN returns_flat AS rt + -- other departments besides the 'appliance' dept cannot be restocked into available inventory + ON ps.sku_id = rt.sku_id AND ps.department = 'appliance' +GROUP BY + ps.sku_id, + ps.name, + pp.unit_price, + ps.description, + ps.department; + + +--- NET_SALES numbers computed from Cummulative Purchases minus Returns +INSERT INTO `net_sales_depot` +SELECT + ps.sku_id AS key_column, + ps.department, + ps.name, + -- Net Sales = (Purchases - Returns) + (IFNULL(SUM(pc.units * pc.unit_price),0.00) - IFNULL(SUM(rt.units * rt.unit_price),0.00)) AS net_sales, + ps.sku_id +FROM product_skus AS ps +INNER JOIN product_pricing AS pp + ON ps.sku_id = pp.sku_id +INNER JOIN departments AS d + ON ps.department = d.department +LEFT JOIN purchases_flat AS pc + ON ps.sku_id = pc.sku_id +LEFT JOIN returns_flat AS rt + ON ps.sku_id = rt.sku_id +GROUP BY + ps.sku_id, + ps.name, + pp.unit_price, + ps.description, + ps.department; \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql new file mode 100644 index 0000000000..6518e8ef98 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql @@ -0,0 +1,18 @@ +CREATE TABLE `departments_source` ( + `department` STRING NOT NULL, + `description` STRING NOT NULL +) +DISTRIBUTED BY HASH(`key`) INTO 6 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'topic' = 'departments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql new file mode 100644 index 0000000000..552747ed6b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql @@ -0,0 +1,19 @@ +CREATE TABLE `departments` ( + `key` STRING NOT NULL, + `department` STRING NOT NULL, + `description` STRING NOT NULL +) +DISTRIBUTED BY HASH(`key`) INTO 6 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'topic' = 'departments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql new file mode 100644 index 0000000000..cf17ea3b57 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql @@ -0,0 +1,4 @@ + +INSERT INTO `departments_flat` +SELECT `department` AS `row_key`, `department`, `description` FROM `departments` + diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql new file mode 100644 index 0000000000..91c67b8063 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql @@ -0,0 +1,109 @@ + +-- Flat table definitions for purchases, returns, and replenishments +CREATE TABLE `purchases_flat` ( + `key` VARBINARY(2147483647), + `customer_id` VARCHAR(2147483647) NOT NULL COMMENT 'Unique identifier for the customer making the purchase.', + `discounts` DOUBLE NOT NULL COMMENT 'Total discounts applied to the item.', + `receipt_id` VARCHAR(2147483647) NOT NULL COMMENT 'Identifier associated with the transaction receipt.', + `sku_id` VARCHAR(2147483647) NOT NULL COMMENT 'SKU identifier for the purchased item.', + `transaction_date` VARCHAR(2147483647) NOT NULL COMMENT 'Date and time of the transaction in ''YYYY-MM-DD HH:MM:SS'' format.', + `unit_price` DOUBLE NOT NULL COMMENT 'Price per unit of the item.', + `units` DOUBLE NOT NULL COMMENT 'Number of units purchased.' +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'raw', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE `returns_flat` ( + `key` VARBINARY(2147483647), + `customer_id` VARCHAR(2147483647) NOT NULL COMMENT 'Unique identifier for the customer making the return.', + `receipt_id` VARCHAR(2147483647) NOT NULL COMMENT 'Identifier associated with the transaction receipt.', + `sku_id` VARCHAR(2147483647) NOT NULL COMMENT 'SKU identifier for the returned item.', + `transaction_date` VARCHAR(2147483647) NOT NULL COMMENT 'Date and time of the transaction in ''YYYY-MM-DD HH:MM:SS'' format.', + `unit_price` DOUBLE NOT NULL COMMENT 'Price per unit of the item.', + `units` DOUBLE NOT NULL COMMENT 'Number of units returns.' +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'raw', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE `replenishments_flat` ( + `key` VARBINARY(2147483647), + `replenishment_id` VARCHAR(2147483647) NOT NULL COMMENT 'Identifier associated with the transaction receipt.', + `sku_id` VARCHAR(2147483647) NOT NULL COMMENT 'SKU identifier for the returned item.', + `transaction_date` VARCHAR(2147483647) NOT NULL COMMENT 'Date and time of the transaction in ''YYYY-MM-DD HH:MM:SS'' format.', + `units` DOUBLE NOT NULL COMMENT 'Number of units returns.', + `vendor_id` VARCHAR(2147483647) NOT NULL COMMENT 'Unique identifier for the customer making the return.' +) +DISTRIBUTED BY HASH(`key`) INTO 1 BUCKETS +WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'raw', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +INSERT INTO `replenishments_flat` +SELECT + r.sku_id AS `key`, + r.replenishment_id, + r.sku_id, + r.transaction_date, + r.units, + r.vendor_id +FROM `replenishments` AS r; + +INSERT INTO `purchases_flat` +SELECT + i.sku_id, AS `key`, + p.customer_id, + i.discounts, + p.receipt_id, + i.sku_id, + p.transaction_date, + i.unit_price, + i.units +FROM `purchases` AS p +CROSS JOIN UNNEST(p.items) AS i (sku_id, units, unit_price, discounts); + +INSERT INTO `returns_flat` +SELECT + i.sku_id, AS `key`, + r.customer_id, + r.receipt_id, + i.sku_id, + r.transaction_date, + i.unit_price, + i.units +FROM `returns` AS r +CROSS JOIN UNNEST(r.items) AS i (sku_id, units, unit_price); + diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql new file mode 100644 index 0000000000..c81dc2c835 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql @@ -0,0 +1,10 @@ +CREATE TABLE product_skus ( + id STRING, + sku_id STRING, + name STRING, + description STRING, + department STRING +) WITH ( + 'changelog.mode' = 'append', + 'scan.startup.mode' = 'earliest-offset' +); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql new file mode 100644 index 0000000000..cca613833a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql @@ -0,0 +1,36 @@ +-- Create a flattened view of the purchases + +CREATE TABLE `purchases_flat` ( + customer_id STRING, + receipt_id STRING, + transaction_date VARCHAR(2147483647), + sku_id STRING, + units DOUBLE NOT NULL, + unit_price DOUBLE, + discounts DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +-- Insert into the purchases_flat table + +INSERT INTO `purchases_flat` +SELECT + p.customer_id, + p.receipt_id, + p.transaction_date, + i.sku_id, + i.units, + i.unit_price, + i.discounts +FROM purchases AS p +CROSS JOIN UNNEST(p.items) AS i (sku_id, units, unit_price, discounts); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql new file mode 100644 index 0000000000..8e1b21907e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql @@ -0,0 +1,29 @@ +-- Create a flattened view of the replenishments +CREATE TABLE `replenishments_flat` ( + replenishment_id STRING, + vendor_id STRING, + transaction_date VARCHAR(2147483647), + sku_id STRING, + units DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +-- Insert into the replenishments_flat table +INSERT INTO `replenishments_flat` +SELECT + r.replenishment_id, + r.vendor_id, + r.transaction_date, + r.sku_id, + r.units +FROM `replenishments` AS r; \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql new file mode 100644 index 0000000000..59474f500c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql @@ -0,0 +1,125 @@ +CREATE TABLE departments ( + `department` STRING, + `description` STRING +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'departments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE product_skus ( + id STRING, + sku_id STRING, + name STRING, + description STRING, + department STRING +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'product_skus', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE product_pricing ( + id STRING, + sku_id STRING, + unit_price DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'product_pricing', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE purchases ( + id STRING, + receipt_id STRING, + transaction_date STRING, + customer_id STRING, + items ARRAY<ROW< + sku_id STRING, + units DOUBLE, + unit_price DOUBLE, + discounts DOUBLE + >> +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'purchases', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE returns ( + id STRING, + return_id STRING, + receipt_id STRING, + transaction_date STRING, + customer_id STRING, + items ARRAY<ROW< + sku_id STRING, + units DOUBLE, + unit_price DOUBLE + >> +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'returns', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +CREATE TABLE replenishments ( + id STRING, + replenishment_id STRING, + transaction_date STRING, + sku_id STRING, + units DOUBLE, + vendor_id STRING +) WITH ( + 'changelog.mode' = 'append', + 'topic' = 'replenishments', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'key.format' = 'json-registry', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql new file mode 100644 index 0000000000..5563c7fc37 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql @@ -0,0 +1,32 @@ +-- Create a flattened view of the returns +CREATE TABLE `returns_flat` ( + customer_id STRING, + receipt_id STRING, + transaction_date VARCHAR(2147483647), + sku_id STRING, + units DOUBLE, + unit_price DOUBLE +) WITH ( + 'changelog.mode' = 'append', + 'connector' = 'confluent', + 'kafka.cleanup-policy' = 'delete', + 'kafka.compaction.time' = '0 ms', + 'kafka.max-message-size' = '2097164 bytes', + 'kafka.retention.size' = '0 bytes', + 'kafka.retention.time' = '7 d', + 'scan.bounded.mode' = 'unbounded', + 'scan.startup.mode' = 'earliest-offset', + 'value.format' = 'json-registry' +); + +-- Insert into the returns_flat table +INSERT INTO `returns_flat` +SELECT + r.customer_id, + r.receipt_id, + r.transaction_date, + i.sku_id, + i.units, + i.unit_price +FROM `returns` AS r +CROSS JOIN UNNEST(r.items) AS i (sku_id, units, unit_price); \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh new file mode 100755 index 0000000000..7d0bf50eac --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +source ./environment-azure.sh + + +print_lines() { + echo "" + echo "" +} + +print_lines +echo "Checking Azure Storage Account Shared Key Access..." +SHARED_KEY_ACCESS=$(az storage account show -g ${AZURE_RESOURCE_GROUP} --name ${STORAGE_ACCOUNT} --query "allowSharedKeyAccess" --output tsv) +echo "Shared Key Access: ${SHARED_KEY_ACCESS}" +echo "This should be 'true'" + +print_lines +echo "Checking Azure Storage Account Public Network Access..." +PUBLIC_NETWORK_ACCESS=$(az storage account show -g ${AZURE_RESOURCE_GROUP} --name ${STORAGE_ACCOUNT} --query "publicNetworkAccess" --output tsv) +echo "Public Network Access: ${PUBLIC_NETWORK_ACCESS}" +echo "This should be 'Enabled'" + +print_lines +echo "Checking Azure Cosmos DB Account Local Auth Disabled..." +COSMOS_DB_DISABLE_LOCAL_AUTH=$(az cosmosdb show -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --query "disableLocalAuth" --output tsv) +echo "Cosmos DB Local Auth Disabled: ${COSMOS_DB_DISABLE_LOCAL_AUTH}" +echo "This should be 'false'" + +print_lines +echo "Checking Azure Cosmos DB Account Public Network Access..." +COSMOS_DB_PUBLIC_NETWORK_ACCESS=$(az cosmosdb show -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --query "publicNetworkAccess" --output tsv) +echo "Cosmos DB Public Network Access: ${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" +echo "This should be 'Enabled'" + +echo "" +echo "" + +printf "%-45s %-12s %-12s %-10s\n" "Service Setting/Configuration" "Expected" "Actual" "Result" + +# Azure Blob Storage Network Access +if [ "${PUBLIC_NETWORK_ACCESS}" == "Enabled" ]; then + result="Pass" +else + result="Fail" +fi +printf "%-45s %-12s %-12s %-10s\n" "Azure Blob Storage Network Access Enabled" "Enabled" "${PUBLIC_NETWORK_ACCESS}" "${result}" + +# Azure Blob Storage Shared Key +if [ "${SHARED_KEY_ACCESS}" == "true" ]; then + result="Pass" +else + result="Fail" +fi +printf "%-45s %-12s %-12s %-10s\n" "Azure Blob Storage Shared Key Allowed" "true" "${SHARED_KEY_ACCESS}" "${result}" + +# Cosmos DB Public Network Access +if [ "${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" == "Enabled" ]; then + result="Pass" +else + result="Fail" +fi +printf "%-45s %-12s %-12s %-10s\n" "Cosmos DB Public Network Access Enabled" "Enabled" "${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" "${result}" + +# Cosmos DB Local Auth Disabled +if [ "${COSMOS_DB_DISABLE_LOCAL_AUTH}" == "false" ]; then + result="Pass" +else + result="Fail" +fi +printf "%-45s %-12s %-12s %-10s\n" "Cosmos DB Local Auth Disabled" "false" "${COSMOS_DB_DISABLE_LOCAL_AUTH}" "${result}" + diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh new file mode 100755 index 0000000000..5c0875e0c8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +export AZURE_RESOURCE_GROUP="confluent-hackathon" + +export COSMOS_DB_ACCOUNT="cfltizzya04qga" + +export STORAGE_ACCOUNT="cfltizzya04qga" \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh new file mode 100755 index 0000000000..3690490763 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh @@ -0,0 +1,8 @@ + +#!/bin/bash + +# export CONFLUENT_ORGANIZATION_ID="1b2a7da3-709a-4562-9553-3cd6397c7388" + +export CONFLUENT_ORGANIZATION_ID="ca4d5cac-8257-49fd-af5b-1d1692f5f125" +export CONFLUENT_ENVIRONMENT_ID="env-6ggk2q" +export CONFLUENT_KAFKA_CLUSTER_ID="lkc-jyw7j2" diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh new file mode 100755 index 0000000000..96a7c25169 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +source ./environment-azure.sh + +az storage account update -g ${AZURE_RESOURCE_GROUP} --name ${STORAGE_ACCOUNT} --allow-shared-key-access true + +az storage account update \ + --name ${STORAGE_ACCOUNT} \ + --resource-group ${AZURE_RESOURCE_GROUP} \ + --public-network-access Enabled \ + --default-action Allow + diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh new file mode 100755 index 0000000000..2da754ccd7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +source ./environment-azure.sh + +# Enable Public Network Access +az cosmosdb update -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --public-network-access Enabled --debug + +# Enable Local Authentication with Keys +az resource update -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --resource-type "Microsoft.DocumentDB/databaseAccounts" --set properties.disableLocalAuth=false --debug + diff --git a/073-AIWithConfluentOnAzure/README.md b/073-AIWithConfluentOnAzure/README.md new file mode 100644 index 0000000000..f693803823 --- /dev/null +++ b/073-AIWithConfluentOnAzure/README.md @@ -0,0 +1,51 @@ +# What The Hack - AI With Confluent On Azure + +## Introduction + +This hackathon immerses you in building a real-time AI agent using **Confluent Cloud on Microsoft Azure**. You’ll learn how Confluent’s data streaming platform—based on Apache Kafka—can connect and process retail data in real time, enabling AI-driven insights that keep pace with constantly changing business conditions [1][2]. Whether it’s ingesting product SKUs or synchronizing inventory levels, Confluent Cloud on Azure offers a unified, scalable, and secure platform to design near real-time pipelines and deliver accurate, intelligent solutions. + +Throughout this hack, you’ll capture data from diverse sources—such as transaction logs, returns, and purchase records—and then transform or enrich that data using Apache Flink or ksqlDB. The result is an always up-to-date data backbone, ready to power AI-driven applications that swiftly respond to customer needs, supplier demands, and dynamic inventory scenarios [3][4]. + + +## Learning Objectives + +By completing this hack, you will: + +- **Set up a real-time streaming environment** on Confluent Cloud in Azure, incorporating best practices for scalability, reliability, and security. +- **Ingest and process diverse data sources** using Apache Kafka, exploring how pre-built Confluent connectors facilitate end-to-end data pipelines. +- **Apply basic stream processing** through ksqlDB or Apache Flink to merge, filter, or aggregate event data in real time. +- **Sync transformed data to Azure services** like Cosmos DB or Azure AI Search, ensuring your AI agent always has a near real-time view of retail operations. +- **Lay the groundwork for AI-driven decision-making**, demonstrating how real-time data improves accuracy and responsiveness for both customers and internal stakeholders. + +## Challenges + +- Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** + - Prepare your workstation to work with Azure. +- Challenge 01: **[Configuration of Agentic Resources and Deployment of Backend](Student/Challenge-01.md)** + - Description of challenge +- Challenge 02: **[Configuration of Chat Interface and Frontend](Student/Challenge-02.md)** + - Description of challenge +- Challenge 03: **[Simulation of Employee - Reports, Status etc](Student/Challenge-03.md)** + - Description of challenge +- Challenge 04: **[Simulation of Suppliers - Replenishments](Student/Challenge-04.md)** + - Description of challenge +- Challenge 05: **[Simulation of Customers - Purchases and Returns](Student/Challenge-05.md)** + - Description of challenge + +## Prerequisites + +- Your own Azure subscription with Owner access +- Visual Studio Code +- Azure CLI + +## References +- 1 https://www.confluent.io/apache-kafka-vs-confluent/ +- 2 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/overview +- 3 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create +- 4 https://www.confluent.io/hub/ + +## Contributors + +- Andy Huang +- Israel Ekpo +- Juan Llovet de Casso diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-00.md b/073-AIWithConfluentOnAzure/Student/Challenge-00.md new file mode 100644 index 0000000000..61aa89aa4b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -0,0 +1,100 @@ +# Challenge 00 - Prerequisites - Ready, Set, GO! + +**[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) + +**_This is a template for "Challenge Zero" which focuses on getting prerequisites set up for the hack. The italicized text provides hints & examples of what should or should NOT go in each section._** + +**_We have included links to some common What The Hack pre-reqs in this template. All common prerequisite links go to the WTH-CommonPrerequisites page where there are more details on what each tool's purpose is._** + +**_You should remove any common pre-reqs that are not required for your hack. Then add additional pre-reqs that are required for your hack in the Description section below._** + +**_You should remove all italicized & sample text in this template and replace with your content._** + +## Introduction + +Thank you for participating in the AIWithConfluentOnAzure What The Hack. Before you can hack, you will need to set up some prerequisites. + +## Common Prerequisites + +We have compiled a list of common tools and software that will come in handy to complete most What The Hack Azure-based hacks! + +You might not need all of them for the hack you are participating in. However, if you work with Azure on a regular basis, these are all things you should consider having in your toolbox. + +<!-- If you are editing this template manually, be aware that these links are only designed to work if this Markdown file is in the /xxx-HackName/Student/ folder of your hack. --> + +- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) +- [Windows Subsystem for Linux](../../000-HowToHack/WTH-Common-Prerequisites.md#windows-subsystem-for-linux) +- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) + - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) + - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) + - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) + - [Azure PowerShell CmdLets](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-powershell-cmdlets) + - [Azure Cloud Shell](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cloud-shell) +- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) + - [VS Code plugin for ARM Templates](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code-plugins-for-arm-templates) +- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) + +## Description + +_This section should clearly state any additional prerequisite tools that need to be installed or set up in the Azure environment that the student will hack in._ + +_While ordered lists are generally not welcome in What The Hack challenge descriptions, you can use one here in Challenge Zero IF and only IF the steps you are asking the student to perform are not core to the learning objectives of the hack._ + +_For example, if the hack is on IoT Devices and you want the student to deploy an ARM/Bicep template that sets up the environment they will hack in without them needing to understand how ARM/Bicep templates work, you can provide step-by-step instructions on how to deploy the ARM/Bicep template._ + +_Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack. You should leave the sample text below in that refers to the Resources.zip file._ + +**\*NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resources.zip file provided by the coach.\* + +**\*NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.\* + +_Sample challenge zero text for the IoT Hack Of The Century:_ + +Now that you have the common pre-requisites installed on your workstation, there are prerequisites specifc to this hack. + +Your coach will provide you with a Resources.zip file that contains resources you will need to complete the hack. If you plan to work locally, you should unpack it on your workstation. If you plan to use the Azure Cloud Shell, you should upload it to the Cloud Shell and unpack it there. + +Please install these additional tools: + +- [Azure IoT Tools](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools) extension for Visual Studio Code +- .NET SDK 6.0 or later installed on your development machine. This can be downloaded from [here](https://www.microsoft.com/net/download/all) for multiple platforms. + +In the `/Challenge00/` folder of the Resources.zip file, you will find an ARM template, `setupIoTEnvironment.json` that sets up the initial hack environment in Azure you will work with in subsequent challenges. + +Please deploy the template by running the following Azure CLI commands from the location of the template file: +``` +az group create --name myIoT-rg --location eastus +az group deployment create -g myIoT-rg --name HackEnvironment -f setupIoTEnvironment.json +``` + +## Success Criteria + +_Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach._ + +_The success criteria should not be a list of instructions._ + +_Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."_ + +_Sample success criteria for the IoT prerequisites challenge:_ + +To complete this challenge successfully, you should be able to: + +- Verify that you have a bash shell with the Azure CLI available. +- Verify that the ARM template has deployed the following resources in Azure: + - Azure IoT Hub + - Virtual Network + - Jumpbox VM + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +_Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario._ + +**\*Note:** Use descriptive text for each link instead of just URLs.\* + +_Sample IoT resource links:_ + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-01.md b/073-AIWithConfluentOnAzure/Student/Challenge-01.md new file mode 100644 index 0000000000..65ccfa2826 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -0,0 +1,54 @@ +# Challenge 01 - Configuration of Agentic Resources and Deployment of Backend + +[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) + +## Introduction + +In this challenge, you'll focus on deploying the backend API that will serve as the foundation for your real-time AI agent. This API will eventually consume data streamed through Confluent Cloud on Azure and surface intelligent responses based on the latest available information. + +## Description + +*Need to Update once we confirm architecture* + + +## Success Criteria + +To complete this challenge successfully, you should be able to: +- Show that your Azure resources and API have been deployed +- Verify that the API is reachable and responsive. + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-02.md b/073-AIWithConfluentOnAzure/Student/Challenge-02.md new file mode 100644 index 0000000000..6a5379954e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -0,0 +1,59 @@ +# Challenge 02 - Configuration of Chat Interface and Frontend + +[< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) + + +## Pre-requisites + +You must complete **Challenge 01** before starting this challenge. The backend API must be successfully deployed and reachable, as the frontend will depend on it for communication and functionality. + +## Introduction + +In this challenge, you'll configure and deploy the frontend user interface that interacts with your backend API. This frontend UI will allow users to send and receive messages to the AI agent powered by real-time streaming data from Confluent Cloud. **Need to update as I am just filling in generic verbiage** + + +## Description + +**Need to Update as we get details of infrastructure. + +## Success Criteria + +To complete this challenge successfully, you should be able to: +- Show that your frontend and related Azure resources have been deployed. +- Verify that the frontend can communicate with the backend API and receive a valid response. + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-03.md b/073-AIWithConfluentOnAzure/Student/Challenge-03.md new file mode 100644 index 0000000000..539e22e5a1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -0,0 +1,80 @@ +# Challenge 03 - Simulation of Employee Persona + +[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) + + +## Pre-requisites + +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend interface must be fully deployed and functional, as this challenge builds on top of the running application infrastructure. + + +## Introduction + +In this challenge, you'll simulate the experience of an employee interacting with the AI agent to perform various business-critical operations. This persona has access to operational data such as purchases, returns, and inventory, and can also perform updates to the product catalog in near real time. + +The goal of this challenge is to observe how changes initiated through the agent are processed and reflected across systems in near real time using Confluent Cloud on Azure. These updates—whether querying data or modifying records—flow through Kafka topics, are processed via stream processors like Flink or ksqlDB, and are reflected in the destination datastore with minimal delay. + + +## Description + +In this challenge, you will authenticate as an employee and issue commands to the AI agent to retrieve and update retail operations data. These interactions are routed through the backend API, processed via Confluent Cloud's real-time data infrastructure, and ultimately reflected in the destination datastore. + +- Authenticate using an employee ID and 4-digit PIN. +- Retrieve summaries for a specific date: + - Total purchases + - Total replenishments + - Total returns + - Net sales (purchases - returns) +- Query current inventory level of a specific SKU. +- Modify inventory-related data: + - Change the maximum inventory level of a specific SKU. + - Update the unit price of a specific SKU. + - Add a new SKU to the product catalog. + - Modify the list of SKUs a vendor is authorized to replenish. + +All modifications should propagate through Confluent Cloud and be reflected in the destination data store (e.g., Cosmos DB or Azure AI Search) in near real time. + + +## Success Criteria + +To complete this challenge successfully, you should be able to: +- Show that employee users can authenticate using ID and PIN. +- Show at least three successful read operations. +- Show at least two successful write operations. +- Verify that data changes propagate through Confluent Cloud and are reflected in the destination data store in near real time. + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-04.md b/073-AIWithConfluentOnAzure/Student/Challenge-04.md new file mode 100644 index 0000000000..f225b41ef7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -0,0 +1,73 @@ +# Challenge 04 - Simulation of Suppliers - Replenishments + +[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) + + +## Pre-requisites + +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend, frontend, and employee data operations must be functional to ensure supplier-related workflows integrate with the rest of the system. + + +## Introduction + +In this challenge, you’ll take on the role of a vendor or supplier interacting with the AI agent to monitor and replenish inventory levels. These interactions are authorized and scoped to SKUs each vendor is allowed to manage. + +The goal of this challenge is to observe how inventory replenishment operations are processed in near real time through Confluent Cloud on Azure and reflected immediately in downstream systems like Cosmos DB or Azure AI Search. + + +## Description + +Vendors will authenticate into the system using their vendor ID and 4-digit PIN. Once authenticated, the vendor will use the AI agent to retrieve SKU-level data and issue replenishment commands. + +- Authenticate using vendor ID and 4-digit PIN. +- Retrieve: + - A list of SKUs the vendor is authorized to replenish. + - The Maximum Inventory Level (MIL) for each of those SKUs. + - The current inventory level of a specific authorized SKU. +- Replenish the inventory of an authorized SKU up to 100% of its MIL. + +All replenishment updates should be routed through Confluent Cloud and reflected in the destination data store in near real time. + +## Success Criteria + +To complete this challenge successfully, you should be able to: +- Show that vendor users can authenticate using ID and PIN. +- Verify that you are able to retrie a authorized SKUs and their inventory information. +- Verify a successful replenishment operation that updates inventory to the correct MIL occurs. +- Verify that inventory updates are reflected in the destination data store in near real time through Confluent Cloud. + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-05.md b/073-AIWithConfluentOnAzure/Student/Challenge-05.md new file mode 100644 index 0000000000..86387ad878 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Challenge-05.md @@ -0,0 +1,78 @@ +# Challenge 05 - Simulation of Customers - Purchases and Returns + +[< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** + + +## Pre-requisites (Optional) + +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend chat interface must be fully deployed and functional for customer interactions to work correctly. + + +## Introduction + +In this challenge, you'll simulate how customers interact with the AI agent to browse products, make purchases, and request returns. These interactions represent real-world commerce flows and depend on accurate, up-to-date inventory and pricing information. + +The goal of this challenge is to observe how customer-facing operations impact the backend in real time. All updates made through the agent—such as purchasing or returning SKUs—should flow through Confluent Cloud and be reflected in the destination datastore in near real time. + + +## Description + +Customers authenticate using a customer ID and 4-digit PIN. Once signed in, they should be able to browse available SKUs, check stock status, make purchases, and return eligible items. + +- Authenticate using customer ID and 4-digit PIN. +- Retrieve: + - A list of all SKUs available in the store, regardless of inventory. + - A list of SKUs currently in stock. + - A list of SKUs currently out of stock. + - The status of a specific SKU, including unit price, inventory level, and discount (if any). +- Add an SKU to the shopping cart (up to available inventory). +- Make a purchase for all items in the cart, generating a receipt ID. +- Retrieve transaction details for a specific receipt ID. +- Return an SKU from a previous purchase by providing a receipt ID, as long as the return is within 14 days of the purchase date. + +All purchase and return actions should be processed via Confluent Cloud and reflected in the destination datastore in near real time. + +## Success Criteria + +To complete this challenge successfully, you should be able to: +- Show that customer users can authenticate using ID and PIN. +- Verify you can retrie the product catalog and inventory information. +- Complete a purchase flow with a generated receipt ID. +- Show how you can return a purchased item within the allowed return window. +- Verify that purchases and returns are reflected in the destination data store in near real time through Confluent Cloud. + +## Learning Resources + +_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ + +*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + +***Note:** Use descriptive text for each link instead of just URLs.* + +*Sample IoT resource links:* + +- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) +- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) +- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) + +## Tips + +*This section is optional and may be omitted.* + +*Add tips and hints here to give students food for thought. Sample IoT tips:* + +- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. +- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. + +## Advanced Challenges (Optional) + +*If you want, you may provide additional goals to this challenge for folks who are eager.* + +*This section is optional and may be omitted.* + +*Sample IoT advanced challenges:* + +Too comfortable? Eager to do more? Try these additional challenges! + +- Observe what happens if your IoTDevice is separated from its thingamajig. +- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/073-AIWithConfluentOnAzure/Student/Resources/.gitkeep b/073-AIWithConfluentOnAzure/Student/Resources/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore new file mode 100644 index 0000000000..aadd0f3246 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore @@ -0,0 +1,7 @@ + +Dockerfile.* +.env.sh +.env.sh.* +.venv +__pycache__ + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example new file mode 100644 index 0000000000..d79c2c25cc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example @@ -0,0 +1,50 @@ +#!/bin/bash + +# This is for the service principal in Azure +export AZURE_SUBSCRIPTION_ID="enter-your-subscription-id-here" +export AZURE_CLIENT_ID="enter-your-client-id-here" +export AZURE_CLIENT_SECRET="enter-your-client-secret-here" +export AZURE_TENANT_ID="enter-your-tenant-id-here" + +# Azure AI Search Credentials +export AZURE_AI_SEARCH_API_VERSION="2025-03-01-preview" # keep or change as needed +export AZURE_AI_SEARCH_ENDPOINT="https://your-search-service.search.windows.net" +export AZURE_AI_SEARCH_API_KEY="enter-your-ai-search-api-key-here" + +# Azure Cosmos DB Credentials +export COSMOS_CONNECTION_STRING="AccountEndpoint=https://your-cosmos-account.documents.azure.com:443/;AccountKey=enter-your-cosmos-key-here;" +export COSMOS_ENDPOINT="https://your-cosmos-account.documents.azure.com:443/" +export COSMOS_DATABASE_NAME="enter-your-database-name-here" + +# This is from Azure Redis Cache +export REDIS_HOST="your-redis-cache-name.redis.cache.windows.net" +export REDIS_PORT="6380" +export REDIS_PASSWORD="enter-your-redis-password-here" + +# This is from AI Foundry (Azure OpenAI) +export AZURE_OPENAI_ENDPOINT="https://your-openai-resource.openai.azure.com/" +export AZURE_OPENAI_API_KEY="enter-your-openai-api-key-here" +export AZURE_OPENAI_MODEL_NAME="gpt-4o-mini" +export OPENAI_API_VERSION="2025-01-01-preview" + +# MCP Services +export MCP_SERVICE_ENDPOINT_INVENTORY="http://localhost:8080/mcp" +export MCP_SERVICE_ENDPOINT_REPLENISHMENT="http://localhost:8081/mcp" +export MCP_SERVICE_ENDPOINT_SHOPPING="http://localhost:8082/mcp" + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# source ~/Microsoft/Confluent-WTH/.confluent-environment.sh +# confluent kafka topic produce ${topic_name} --parse-key --delimiter "::" --keyformat + + +# MCP Services \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md new file mode 100644 index 0000000000..ca502357ce --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md @@ -0,0 +1,82 @@ +## How to Build the Docker Images + +Navigate to the agentic_application directory and run the following commands to build each Docker image + + +```bash +# Navigate to the agent application directory +cd agentic_application + +# Create the base Docker image +docker build -t izzyacademy/confluent-hackathon:3.2.1 -t izzyacademy/confluent-hackathon:latest -f Dockerfile.base . + +# Build the Docker image for the Inventory MCP service +docker build -t izzyacademy/inventory:3.2.1 -t izzyacademy/inventory:latest -f Dockerfile.inventory . + +# Build the Docker image for the Replenishment MCP service +docker build -t izzyacademy/replenishment:3.2.1 -t izzyacademy/replenishment:latest -f Dockerfile.replenishment . + +# Build the Docker image for the Employee Agent Experience +docker build -t izzyacademy/employee:3.2.1 -t izzyacademy/employee:latest -f Dockerfile.employee . + +# Build the Docker image for the Supplier Agent Experience +docker build -t izzyacademy/supplier:3.2.1 -t izzyacademy/supplier:latest -f Dockerfile.supplier . + + +``` + +## How to Run the Dockers Containers with Docker Compose + +These are the steps: + +- Navigate to the compose directory +- ensure that the environment variables in the `shared_environment_variables.env` file are accurate +- make sure the `shared_environment_variables.env` file is in the current directory +- kick off the docker compose collection +- shut it down when you are done with you test/demo + +```bash + +# Navigate to the agent application directory +cd compose + +# Run the compose file as follows +docker-compose up + +# Tear down when you are done +docker-compose down --remove-orphans + +``` + +### How to Log on to the Containers + +```bash +# List all the active containers +docker ps + + +# Log into the employee container +docker exec -it compose-employee-1 /bin/bash + +# Log into the supplier container +docker exec -it compose-supplier-1 /bin/bash + +# Log into the customer container +docker exec -it compose-customer-1 /bin/bash + +``` + +Once you are in the container, you can execute each agent as follows: + +```bash + +# this is the employee experience +uv run agent_employee_experience.py + +# this is the supplier or vendor experience +uv run agent_supplier_experience.py + +# this is for the customer experience to search SKUs, make purchases, return previous purchases +uv run agent_customer_experience.py + +``` \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base new file mode 100644 index 0000000000..4a48a376e8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base @@ -0,0 +1,15 @@ +# Ubuntu 24.04 base +FROM ubuntu:24.04 + +# Install curl + certs (needed to fetch uv); keep image slim +RUN apt-get update \ + && apt-get install -y --no-install-recommends coreutils \ + curl ca-certificates vim \ + iputils-ping telnet netcat-openbsd \ + && rm -rf /var/lib/apt/lists/* + +# Install uv (to /root/.local/bin/uv by default) and make it globally available +RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ + && ln -s /root/.local/bin/uv /usr/local/bin/uv \ + && uv --version + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer new file mode 100644 index 0000000000..77aa635b65 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer @@ -0,0 +1,16 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.agent-customer.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee new file mode 100644 index 0000000000..a78fe24cd1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee @@ -0,0 +1,17 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder "agentic_application" into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.agent-employee.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory new file mode 100644 index 0000000000..ae9a2c1596 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory @@ -0,0 +1,18 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.mcp-inventory.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +EXPOSE 8080 + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment new file mode 100644 index 0000000000..3026c9315f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment @@ -0,0 +1,18 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.mcp-replenishment.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +EXPOSE 8081 + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping new file mode 100644 index 0000000000..c1d98e5199 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping @@ -0,0 +1,18 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.mcp-shopping.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +EXPOSE 8082 + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier new file mode 100644 index 0000000000..e62da83f92 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier @@ -0,0 +1,16 @@ +# Base Container image from Ubuntu 24.04 +FROM izzyacademy/confluent-hackathon:3.2.1 + +# Set working directory inside the container +WORKDIR /software + +# Copy everything from the current folder into /software in the image +COPY . . + +# Copy over the specific entrypoint script +COPY entrypoints/entrypoint.agent-supplier.sh /software/entrypoint.sh + +# Make the entrypoint script executable +RUN chmod 0775 /software/entrypoint.sh + +ENTRYPOINT ["/software/entrypoint.sh"] \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE new file mode 100644 index 0000000000..30d2ba5f4d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Israel Ekpo + +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. diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md new file mode 100644 index 0000000000..d5b470279b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md @@ -0,0 +1,85 @@ + +We need to do the following +- define Pydantic Objects for all the schemas +- Department +- Product +- ShoppingCartItem +- ShoppingCart + + + +- we need to set up AI Search INDEX for departments and products (SKU and PRICING) + + +### Customers +Customers of the grocery company +- angela@contosocustomers.ai +- patrick@contosocustomers.ai +- darcy@contosovendors.ai +- mikhail@contosogroceries.ai +- jacob@contosogroceries.ai + +### Employees +Employees of the Grocery company +- james@contosogroceries.ai +- charlotte@contosogroceries.ai +- andy@contosogroceries.ai +- juan@contosogroceries.ai +- jason@contosogroceries.ai +- devanshi@contosogroceries.ai + +### Vendors +Global can supply anything but the rest only focus on one department +- kroger@contosovendors.ai +- costco@contosovendors.ai +- global@contosovendors.ai + +## Activate the Virtual Environment + +```bash +source .env.sh +source .venv/bin/activate +``` + +# Run the MCP Services + +````bash +uv run mcp_service.py --service inventory --port 8080 + +uv run mcp_service.py --service replenishment --port 8081 + +uv run mcp_service.py --service shopping --port 8082 +```` + + +# Run the Agents + +````bash + +uv run agent_employee_experience.py + +uv run agent_supplier_experience.py + +uv run agent_customer_experience.py + +```` + +### Run the MCP Inspector + +npx @modelcontextprotocol/inspector + + +### Network Debugging Tools + +```bash + +apt-get install -y iputils-ping telnet vim + +``` + + + +### Testing Nodes + +- Customer ID: jacob@contosogroceries.ai +- Receipt ID: 100001 \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md new file mode 100644 index 0000000000..c193286e15 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md @@ -0,0 +1,3 @@ + +# Contoso Retail Application + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md new file mode 100644 index 0000000000..d295efbb3a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md @@ -0,0 +1,142 @@ +## Setting up the Virtual Environment + +Run the following command from the `agentic_application` folder to create the virtual environment: + +```bash + +uv venv + +``` + +## Activating the Virtual Environment + +You can run these commands to activiate the virtual environment + +### On Mac OS X or Linux + +```bash + +source .venv/bin/activate + +``` + +### On Windows + +```bash + +# If you are using Powershell +.venv\Scripts\Activate.ps1 + +# If you are using the Command Pallete +.venv\Scripts\activate.bat + +``` + +## Loading your Environment Variables + +Run the following command to load the environment variables before running the agents + +```bash + +source .env.sh + +``` + +## Running the MCP Servers + +You can run these commands to start up the MCP servers for the applications + +Make sure to `use a dedicated tab` for each service + +```bash +uv run mcp_service.py --service inventory --port 8080 + +uv run mcp_service.py --service replenishment --port 8081 + +uv run mcp_service.py --service shopping --port 8082 + +``` + +### Debugging the MCP Servers + +If you are having trouble or need to validate the MCP servers before running the agents you can use this tool below + +```bash +npx @modelcontextprotocol/inspector +``` + +### Running the Agent Experiences + +You can run these commands after the MCP servers have booted up: + +Make sure you use `a dedicated tab` for each experience + +````bash + +# this is the employee experience +uv run agent_employee_experience.py + +# this is the supplier or vendor experience +uv run agent_supplier_experience.py + +# this is for the customer experience to search SKUs, make purchases, return previous purchases +uv run agent_customer_experience.py + +```` + + +## How to Run the Dockers Containers with Docker Compose + +These are the steps: + +- Navigate to the compose directory +- ensure that the environment variables in the `shared_environment_variables.env` file are accurate +- make sure the `shared_environment_variables.env` file is in the current directory +- kick off the docker compose collection +- shut it down when you are done with you test/demo + +```bash + +# Navigate to the agent application directory +cd compose + +# Run the compose file as follows +docker-compose up + +# Tear down when you are done +docker-compose down --remove-orphans + +``` + +### How to Log on to the Containers + +```bash +# List all the active containers +docker ps + + +# Log into the employee container +docker exec -it compose-employee-1 /bin/bash + +# Log into the supplier container +docker exec -it compose-supplier-1 /bin/bash + +# Log into the customer container +docker exec -it compose-customer-1 /bin/bash + +``` + +Once you are in the container, you can execute each agent as follows: + +```bash + +# this is the employee experience +uv run agent_employee_experience.py + +# this is the supplier or vendor experience +uv run agent_supplier_experience.py + +# this is for the customer experience to search SKUs, make purchases, return previous purchases +uv run agent_customer_experience.py + +``` \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py new file mode 100644 index 0000000000..8a0eb485c3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +from pydantic_graph import End, Graph + +from contoso_retail_application import ReturnsDao, PurchasesDao, CustomerDependency, CustomerTransactionState, \ + StartNode, MainMenu, FinishNode, ShopInventory, ReturnPriorPurchase, BrowseInventory, FinalizeShopping, \ + FinalizeReturns + + +async def main(): + r_dao = ReturnsDao() + p_dao = PurchasesDao() + + # Setting up the initial state and graph dependencies + transaction_dependency = CustomerDependency(purchases_dao=p_dao, returns_dao=r_dao) + transaction_state = CustomerTransactionState() + + # Listing all possible nodes within our state machine + graph_nodes = (StartNode, MainMenu, FinishNode, ReturnPriorPurchase, ShopInventory, BrowseInventory, FinalizeShopping, FinalizeReturns) + + # Constructing the Graph object with all the nodes + customer_experience_graph = Graph(nodes=graph_nodes, name="Customer Experience", state_type=CustomerTransactionState) + + # Setting the start node, initial state and graph dependencies + async with customer_experience_graph.iter(start_node=StartNode(), state=transaction_state, deps=transaction_dependency) as run: + current_node = run.next_node + while not isinstance(current_node, End): + print('Node', current_node) + current_node = await run.next(current_node) + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py new file mode 100644 index 0000000000..9b3836803e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py @@ -0,0 +1,68 @@ +import os + +from pydantic_ai import Agent +from pydantic_ai.mcp import MCPServerStreamableHTTP +from pydantic_ai.messages import ModelRequest, ModelResponse +from rich.prompt import Prompt + +from contoso_retail_application import ai_foundry_model + +instructions = """ +You are an agent called Mikhail and you help employees of Contoso Groceries (an online grocery store) to get information about the following: + + - Names of departments available in the grocery store + - The prices for different product SKUs in the grocery store + - Inventory levels for different product SKUs in the grocery store + - Net sales reports for different product SKUs in the grocery store + + Please use the data from tools provided and do not make up any information. + + If you cannot answer a question, please let the user know that you cannot answer the question. + +Whenever the response is a list of items, always convert it into a clean, readable Markdown table. + +Formatting rules for Markdown table dataset: +- Always include a header row with clear column names. +- Auto-detect the best column names based on the data (e.g., "Item", "Description", "Value", "Date"). +- Keep the table compact, aligned, and visually appealing. +- If there are more than 5 items, add alternating row shading (if the environment supports it). +- If some items have missing fields, leave the cell blank. +- Never return the list as plain text — always return a table. +- Use Markdown tables by default unless explicitly asked for HTML, CSV, or another format. +""" + +async def thank_you_message(): + print("\n\nThank you for using the Employee Experience Agent. Have a wonderful day\n\n") + +async def main(): + + inventory_service_endpoint = os.getenv('MCP_SERVICE_ENDPOINT_INVENTORY') + inventory_service_definition = MCPServerStreamableHTTP(url=inventory_service_endpoint) + mcp_servers: list[MCPServerStreamableHTTP] = [inventory_service_definition] + + # Keeping track of the Message history + message_history: list[ModelRequest | ModelResponse] = [] + + # initial prompt to get started + current_prompt = "\nHow can I help you?" + + + while True: + + user_prompt = Prompt.ask(current_prompt) + employee_experience_agent = Agent(ai_foundry_model, instructions=instructions, toolsets=mcp_servers) + results = await employee_experience_agent.run(user_prompt, message_history=message_history) + print(results.output) + message_history = results.all_messages() + + exit_or_not = Prompt.ask("\nIs there anything else you would like me to assist you with?", choices=['y','n']) + + if exit_or_not == 'n': + await thank_you_message() + break + current_prompt = "\nWhat else would you like me to help you with?" + + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py new file mode 100644 index 0000000000..3ab775b960 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py @@ -0,0 +1,74 @@ +import os + +from pydantic_ai import Agent +from pydantic_ai.mcp import MCPServerStreamableHTTP +from pydantic_ai.messages import ModelRequest, ModelResponse +from rich.prompt import Prompt + +from contoso_retail_application import ai_foundry_model, StaticDataset + +instructions = """ +You are an agent called Andrew and you help suppliers of Contoso Groceries (an online grocery store) to do the following tasks: + + - Check the inventory levels of product SKUs for the "appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood" departments. + - Check inventory levels for all SKUs for a specific department + - Replenish inventory for specific product SKUs + - Replenish inventory for all product SKUs for a specific department + + Please use the data from tools provided and do not make up any information. + + If you cannot answer a question, please let the user know that you cannot answer the question. + +Whenever the response is a list of items, always convert it into a clean, readable Markdown table. + +Formatting rules for Markdown table dataset: +- Always include a header row with clear column names. +- Auto-detect the best column names based on the data (e.g., "Item", "Description", "Value", "Date"). +- Keep the table compact, aligned, and visually appealing. +- If there are more than 5 items, add alternating row shading (if the environment supports it). +- If some items have missing fields, leave the cell blank. +- Never return the list as plain text — always return a table. +- Use Markdown tables by default unless explicitly asked for HTML, CSV, or another format. +""" + +valid_suppliers = StaticDataset.get_vendor_identifiers() + +async def thank_you_message(): + print("\n\nThank you for using the Supplier Experience Agent. Have a wonderful day\n\n") + +async def main(): + + replenishment_service_endpoint = os.getenv('MCP_SERVICE_ENDPOINT_REPLENISHMENT') + replenishment_service_definition = MCPServerStreamableHTTP(url=replenishment_service_endpoint) + mcp_services = [replenishment_service_definition] + + # Keeping track of the Message history + message_history: list[ModelRequest | ModelResponse] = [] + + # initial prompt to get started + current_prompt = "\nHow can I help you?" + + vendor_id: str = Prompt.ask("What is your vendor id?", choices=valid_suppliers, show_choices=False) + agent_system_prompt = f"My vendor id is {vendor_id}" + + while True: + + user_prompt = Prompt.ask(current_prompt) + supplier_experience_agent = Agent(ai_foundry_model, instructions=instructions, system_prompt=agent_system_prompt, toolsets=mcp_services) + + results = await supplier_experience_agent.run(user_prompt, message_history=message_history) + + print(results.output) + message_history = results.all_messages() + + exit_or_not = Prompt.ask("\nIs there anything else you would like me to assist you with?", choices=['y','n']) + + if exit_or_not == 'n': + await thank_you_message() + break + current_prompt = "\nWhat else would you like me to help you with?" + + +if __name__ == '__main__': + import asyncio + asyncio.run(main()) \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py new file mode 100644 index 0000000000..d31671e05d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py @@ -0,0 +1,45 @@ +from .ai_foundry_setup import ai_foundry_model +from .agent_graphs import CustomerDependency, CustomerTransactionState, FinalizeReturns, FinalizeShopping, \ + BrowseInventory, ShopInventory, ReturnPriorPurchase, StartNode, FinishNode, MainMenu +from .data_access_objects import SearchDataAccessObject, ReturnsDao, PurchasesDao, CartManager +from .models import Departments, Department, NetSales, ProductInventory, PurchaseCart, ReturnCart, ReplenishmentLevel, \ + SkuId, PurchaseItem, ReturnItem, Purchase, ReturnTransaction, ReplenishmentItem, DepartmentInventoryConfig +from .service_configuration_inventory import inventory_service +from .service_configuration_replenishment import replenishment_service +from .service_configuration_shopping import shopping_service +from .static_dataset import StaticDataset +from .utils import base64_encode + +__all__ = ( + 'ai_foundry_model', + 'StaticDataset', + 'ReturnsDao', + 'PurchasesDao', + 'CartManager', + 'Departments', + "Department", + 'inventory_service', + 'replenishment_service', + 'shopping_service', + 'SearchDataAccessObject', + 'NetSales', + 'ProductInventory', + 'PurchaseCart', + 'ReturnCart', + 'DepartmentInventoryConfig', + 'base64_encode', + "ReplenishmentLevel", + "SkuId", "PurchaseItem", "ReturnItem", "Purchase", "ReturnTransaction", "ReplenishmentItem", + "CustomerDependency", + "CustomerTransactionState", + "FinalizeReturns", + "FinalizeShopping", + "BrowseInventory", + "ShopInventory", + "ReturnPriorPurchase", + "FinishNode", + "StartNode", + "MainMenu", +) + + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py new file mode 100644 index 0000000000..69401ec1cb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +from dataclasses import dataclass + +from pydantic_graph import BaseNode, GraphRunContext, End +from rich.prompt import Prompt, IntPrompt + +from .models import SkuId +from .data_access_objects import ReturnsDao, PurchasesDao +from .static_dataset import StaticDataset + + +@dataclass +class CustomerDependency: + returns_dao: ReturnsDao + purchases_dao: PurchasesDao + +@dataclass +class CustomerTransactionState: + customer_id: str | None = None + active_return_cart: bool = False + active_shopping_cart: bool = False + shopping_cart_id: str | None = None + receipt_id: str | None = None + return_cart_id: str | None = None + +@dataclass +class FinalizeReturns(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> FinishNode | ReturnPriorPurchase: + pass + +@dataclass +class FinalizeShopping(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> FinishNode | ShopInventory: + pass + +@dataclass +class BrowseInventory(BaseNode[CustomerTransactionState, CustomerDependency]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState, CustomerDependency]) -> MainMenu | ShopInventory: + pass + + +@dataclass +class ShopInventory(BaseNode[CustomerTransactionState, CustomerDependency]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState, CustomerDependency]) -> MainMenu | BrowseInventory | FinalizeShopping: + pass + + +@dataclass +class ReturnPriorPurchase(BaseNode[CustomerTransactionState, CustomerDependency]): + returns_dao: ReturnsDao = None + purchases_dao: PurchasesDao = None + + async def run(self, ctx: GraphRunContext[CustomerTransactionState, CustomerDependency]) -> MainMenu | FinalizeReturns: + self.returns_dao = ctx.deps.returns_dao + self.purchases_dao = ctx.deps.purchases_dao + + prompt_string = """ + Welcome to Customer Returns: + Enter 1 to Start the Return Process + Enter 7 to Return to the Main Menu + """ + menu_options: list[str] = ["1", "7"] + selected_option: int = IntPrompt.ask(prompt=prompt_string, choices=menu_options, show_choices=False) + + if selected_option == 7: + return MainMenu() + else: + return await self.handle_returns(state=ctx.state) + + async def init_returns(self, state: CustomerTransactionState): + + if not state.active_return_cart: + cart = self.returns_dao.generate_new_cart(receipt_id=state.receipt_id, customer_id=state.customer_id) + state.active_return_cart = True + state.return_cart_id = cart.cart_id + + async def keep_processing_returns(self, state: CustomerTransactionState) -> int: + + print("Thank you for entering your receipt id") + valid_options = ["1", "2", "3", "4", "5"] + prompt_message = """ + What would you like to do next: + 1: Review items from the previous purchase + 2: Review current items you are about to return + 3: Add an item to the return cart. This will add all the units for that SKU + 4: Remove an item from the return cart. This will remove all the units for that SKU + 5: Finalize your returns + """ + + await self.init_returns(state) + + selected_option = IntPrompt.ask(prompt_message, choices=valid_options, show_choices=False) + current_receipt_id = state.receipt_id + current_customer_id = state.customer_id + return_cart_id = state.return_cart_id + + if selected_option == 1: + previous_purchase = self.purchases_dao.get_existing_purchase(receipt_id=current_receipt_id, customer_id=state.customer_id) + # TODO: display this using Rich Tables + print("Here is your previous purchase", previous_purchase) + return selected_option + elif selected_option == 2: + # TODO: display this using Rich Tables + current_return_cart = self.returns_dao.get_cart(cart_identifier=state.return_cart_id) + print("Here are the contents of your return cart", current_return_cart) + return selected_option + elif selected_option == 3: + valid_skus = self.purchases_dao.get_existing_purchase_skus(receipt_id=current_receipt_id, customer_id=current_customer_id) + current_prompt = f"Please enter the SKU you would like to add to the return cart {valid_skus}" + selected_sku: SkuId = Prompt.ask(current_prompt, choices=valid_skus) + units_returned = self.purchases_dao.get_existing_purchase_sku_quentity(receipt_id=current_receipt_id, customer_id=current_customer_id, sku_id=selected_sku) + update_confirmation = self.returns_dao.add_item(cart_identifier=return_cart_id, sku_id=selected_sku, quantity=units_returned) + print(f"Return cart updated, {update_confirmation}") + return selected_option + elif selected_option == 4: + valid_return_skus = self.returns_dao.get_active_return_skus(cart_id=return_cart_id) + if len(valid_return_skus) == 0: + print("There are no items in your return cart, yet. Review your previous purchase and select some items to return") + else: + current_prompt = f"Please enter the SKU you would like to remove from the return cart {valid_return_skus}" + selected_sku: SkuId = Prompt.ask(current_prompt, choices=valid_return_skus, show_choices=False) + removal_confirmation = self.returns_dao.remove_item(cart_identifier=return_cart_id, sku_id=selected_sku) + print(f"Return cart updated, {removal_confirmation}") + return selected_option + else: # option 5 was selected + return selected_option + + + async def handle_returns(self, state: CustomerTransactionState) -> FinalizeReturns: + has_valid_receipt_id: bool = False + customer_id = state.customer_id + + while not has_valid_receipt_id: + receipt_id = Prompt.ask("Please enter a valid receipt id") + receipt_lookup = self.purchases_dao.get_existing_purchase(receipt_id=receipt_id, customer_id=customer_id) + if receipt_lookup is None: + print(f"Receipt id {receipt_id} was NOT FOUND!") + continue + + if receipt_lookup.customer_id != customer_id: + print(f"Customer ID on Receipt Id {receipt_id} does not match your customer ID") + continue + + else: + has_valid_receipt_id = True + state.receipt_id = receipt_id + + + continue_returns = await self.keep_processing_returns(state) + while continue_returns != 5: + continue_returns = await self.keep_processing_returns(state) + + return FinalizeReturns() + + + + + +@dataclass +class FinishNode(BaseNode[CustomerTransactionState, None, str]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> End[str]: + print("Thank you for using the Customer Experience at Contoso Groceries where shopping is always a pleasure. Have a nice day") + return End(ctx.state.customer_id) + + +@dataclass +class StartNode(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> MainMenu: + print("Welcome to the Customer Experience at Contoso Groceries where shopping is always a pleasure.") + print("An agent will be with you shortly. Before we get started, let's have your customer identifier so that we can look up your account information to better assist you.") + valid_customer_ids = StaticDataset.get_customer_identifiers() + customer_id: str = Prompt.ask(prompt="Please enter a valid customer id", choices=valid_customer_ids, show_choices=False) + + # Set the customer id property on the shared state + ctx.state.customer_id = customer_id + return MainMenu() + + +@dataclass +class MainMenu(BaseNode[CustomerTransactionState]): + async def run(self, ctx: GraphRunContext[CustomerTransactionState]) -> BrowseInventory | ShopInventory | ReturnPriorPurchase | FinishNode: + prompt_string = """ + Welcome to the Main Menu: + Enter 2 to Browse Inventory + Enter 3 to Start or Continue Shopping + Enter 4 to Start or Continue your Returns + Enter 5 to Exit the Customer Experience + """ + menu_options: list[str] = ["2", "3", "4", "5"] + selected_option: int = IntPrompt.ask(prompt=prompt_string, choices=menu_options, show_choices=False) + + if selected_option == 2: + return BrowseInventory() + elif selected_option == 3: + return ShopInventory() + elif selected_option == 4: + return ReturnPriorPurchase() + else: + return FinishNode() diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py new file mode 100644 index 0000000000..ca0b2dcc1e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py @@ -0,0 +1,9 @@ +import os + +from pydantic_ai.models.openai import OpenAIModelName, OpenAIChatModel + +ai_foundry_model_name = os.getenv('AZURE_OPENAI_MODEL_NAME', 'gpt-4o-mini') + +model_name: OpenAIModelName = ai_foundry_model_name + +ai_foundry_model = OpenAIChatModel(model_name=model_name, provider='azure') \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py new file mode 100644 index 0000000000..961113c4a9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py @@ -0,0 +1,568 @@ +import os +from datetime import datetime +from typing import Any +from zoneinfo import ZoneInfo + +from azure_datastore_utils import SearchClientDao, RedisUtil, CosmosDBUtils + +from .models import NetSales, Departments, Department, ProductInventory, ReplenishmentLevel, DepartmentInventoryConfig +from .models import PurchaseCart, SkuId, PurchaseItem, ReturnCart, ReturnItem, Purchase +from .models import ReturnTransaction, ReplenishmentItem + + +class SearchDataAccessObject: + """Data Access Object (DAO) for querying Azure Cognitive Search indexes. + + This class provides methods to interact with different indexes + such as net sales, product inventory, and departments. It uses + `SearchClientDao` to query Azure Cognitive Search indexes and + maps the results into domain models (e.g., `NetSales`, + `Department`, `ProductInventory`). + """ + + def __init__(self): + """Initialize the DAO with index names for sales, inventory, and departments.""" + self.sales_index = "net_sales" + self.inventory_index = "product_inventory" + self.department_index = "departments_flat" + + def get_departments(self): + """Retrieve all departments from the search index. + + Returns: + list[Department]: A list of `Department` objects. + """ + search_client = SearchClientDao(self.department_index) + + search_text = "*" + sort_order: list[str] = ["department asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order) + + search_results: list[Department] = [] + + for search_item in query_results: + current_item = Department.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_net_sales(self, max_count: int = 250): + """Retrieves the net sales records from the data store. + + Args: + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[NetSales]: A list of `NetSales` objects sorted by department and SKU. + """ + # set up search client + search_client = SearchClientDao(self.sales_index) + + search_text = "*" + sort_order: list[str] = ["department asc", "sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, top=max_count) + + search_results: list[NetSales] = [] + + for search_item in query_results: + current_item = NetSales.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_net_sales_by_sku(self, sku_id: str): + """Retrieve a single net sales record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + NetSales | None: A `NetSales` object if found, otherwise None. + """ + # set up search client + search_client = SearchClientDao(self.sales_index) + + search_text = "*" + query_filter = f"sku_id eq '{sku_id}'" + + query_results = search_client.query_index(search_text=search_text, query_filter=query_filter, + include_total_count=True) + + for search_item in query_results: + current_item = NetSales.from_dict(search_item) + return current_item + + return None + + def get_net_sales_by_department(self, department: Departments, max_count: int = 250): + """Retrieve net sales records filtered by department. + + Args: + department (Departments): The department to filter by. + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[NetSales]: A list of `NetSales` objects for the given department. + """ + search_client = SearchClientDao(self.sales_index) + + search_text = "*" + query_filter = f"department eq '{department}'" + sort_order: list[str] = ["sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, + query_filter=query_filter, top=max_count) + + search_results: list[NetSales] = [] + + for search_item in query_results: + current_item = NetSales.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_inventory_levels(self, max_count: int = 250): + """Retrieve product inventory levels from the search index. + + Args: + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects. + """ + search_client = SearchClientDao(self.inventory_index) + + search_text = "*" + sort_order: list[str] = ["department asc", "sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, top=max_count) + + search_results: list[ProductInventory] = [] + + for search_item in query_results: + current_item = ProductInventory.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_inventory_levels_by_department(self, department: Departments, max_count: int = 250): + """Retrieve product inventory levels filtered by department. + + Args: + department (Departments): The department to filter by. + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects for the given department. + """ + search_client = SearchClientDao(self.inventory_index) + + search_text = "*" + query_filter = f"department eq '{department}'" + sort_order: list[str] = ["sku_id asc"] + + query_results = search_client.query_index(search_text=search_text, order_by=sort_order, + query_filter=query_filter, top=max_count) + + search_results: list[ProductInventory] = [] + + for search_item in query_results: + current_item = ProductInventory.from_dict(search_item) + search_results.append(current_item) + + return search_results + + def get_inventory_levels_by_sku(self, sku_id: str): + """Retrieve a single product inventory record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ProductInventory | None: A `ProductInventory` object if found, otherwise None. + """ + search_client = SearchClientDao(self.inventory_index) + + search_text = "*" + query_filter = f"sku_id eq '{sku_id}'" + + query_results = search_client.query_index(search_text=search_text, query_filter=query_filter) + + for search_item in query_results: + current_item = ProductInventory.from_dict(search_item) + return current_item + + return None + + def get_replenishment_levels(self, max_count: int = 250): + """Retrieve product replenishment levels for all SKUs. + + Args: + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects. + """ + + config_db = DepartmentInventoryConfig() + items = self.get_inventory_levels(max_count=max_count) + + results: list[ReplenishmentLevel] = [] + for current_sku in items: + current_sku_level = ReplenishmentLevel.from_product_inventory(current_sku, config_database=config_db) + results.append(current_sku_level) + + return results + + def get_replenishment_levels_by_department(self, department: Departments, max_count: int = 250): + """Retrieve product replenishment levels filtered by department. + + Args: + department (Departments): The department to filter by. + max_count (int, optional): Maximum number of records to return. Defaults to 250. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects for the given department. + """ + + config_db = DepartmentInventoryConfig() + items = self.get_inventory_levels_by_department(department=department, max_count=max_count) + + results: list[ReplenishmentLevel] = [] + for current_sku in items: + current_sku_level = ReplenishmentLevel.from_product_inventory(current_sku, config_database=config_db) + results.append(current_sku_level) + + return results + + def get_replenishment_level_by_sku(self, sku_id: str): + """Retrieve a single product replenishment level by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ReplenishmentLevel | None: A `ReplenishmentLevel` object if found, otherwise None. + """ + + config_db = DepartmentInventoryConfig() + item = self.get_inventory_levels_by_sku(sku_id=sku_id) + + if item is not None: + return ReplenishmentLevel.from_product_inventory(item, config_database=config_db) + + return None + + +class CartManager: + CART_KEY_PURCHASES = "purchase_cart_" + CART_KEY_RETURNS = "return_cart_" + CART_KEY_REPLENISHMENTS = "replenishment_cart_" + + INITIAL_CART_ID_PURCHASES = 600000 + INITIAL_CART_ID_RETURNS = 700000 + INITIAL_CART_ID_REPLENISHMENTS = 800000 + + def __init__(self): + self.redis_client = RedisUtil() + + @staticmethod + def get_lookup_key(prefix: str, look_up_key: str): + return f"{prefix}{look_up_key}" + + @staticmethod + def get_lookup_key_purchases(look_up_key: str): + return CartManager.get_lookup_key(CartManager.CART_KEY_PURCHASES, look_up_key) + + @staticmethod + def get_lookup_key_returns(look_up_key: str): + return CartManager.get_lookup_key(CartManager.CART_KEY_RETURNS, look_up_key) + + @staticmethod + def get_lookup_key_replenishments(look_up_key: str): + return CartManager.get_lookup_key(CartManager.CART_KEY_REPLENISHMENTS, look_up_key) + + def __get_cart_id(self, lookup_key: str, initial_value: int): + id_exists: bool = self.redis_client.exists(lookup_key) + if not id_exists: + return self.redis_client.increment(lookup_key, initial_value) + return self.redis_client.increment(lookup_key, 1) + + def get_cart_id_purchases(self): + return self.__get_cart_id(CartManager.CART_KEY_PURCHASES, CartManager.INITIAL_CART_ID_PURCHASES) + + def get_cart_id_returns(self): + return self.__get_cart_id(CartManager.CART_KEY_RETURNS, CartManager.INITIAL_CART_ID_RETURNS) + + def get_cart_id_replenishments(self): + return self.__get_cart_id(CartManager.CART_KEY_REPLENISHMENTS, CartManager.INITIAL_CART_ID_REPLENISHMENTS) + + def generate_new_cart_purchases(self, customer_id: str)->PurchaseCart: + purchase_cart_id:int = self.get_cart_id_purchases() + return self.create_cart_purchases(cart_identifier=str(purchase_cart_id), customer_id=customer_id) + + def create_cart_purchases(self, cart_identifier: str, customer_id: str) -> PurchaseCart: + cart = PurchaseCart(cart_id=cart_identifier, customer_id=customer_id, items={}) + cart_entry = cart.model_dump() + + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + self.redis_client.set_json(look_up_key, cart_entry) + return cart + + def get_cart_purchases(self, cart_identifier: str): + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + item = self.redis_client.get_json(look_up_key) + cart = PurchaseCart.from_dict(item) + return cart + + def add_cart_item_purchases(self, cart_identifier: str, sku_id: SkuId, quantity: float): + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + purchase_item = PurchaseItem(sku_id=sku_id, units=quantity, unit_price=0.00, discounts=0.00) + cart = PurchaseCart.from_dict(item) + + cart.add_item(purchase_item) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def remove_cart_item_purchases(self, cart_identifier: str, sku_id: SkuId): + look_up_key = CartManager.get_lookup_key_purchases(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + cart = PurchaseCart.from_dict(item) + cart.remove_item(sku_id=sku_id) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def generate_new_cart_returns(self, receipt_id: str, customer_id: str) -> ReturnCart: + return_cart_id:int = self.get_cart_id_returns() + return self.create_cart_returns(cart_identifier=str(return_cart_id), receipt_id=receipt_id, customer_id=customer_id) + + def create_cart_returns(self, cart_identifier: str, receipt_id: str, customer_id: str) -> ReturnCart: + cart = ReturnCart(cart_id=cart_identifier, receipt_id=receipt_id, customer_id=customer_id, items={}) + cart_entry = cart.model_dump() + + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + self.redis_client.set_json(look_up_key, cart_entry) + return cart + + def add_cart_item_returns(self, cart_identifier: str, sku_id: SkuId, quantity: float): + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + return_item = ReturnItem(sku_id=sku_id, units=quantity, unit_price=0.00) + cart = ReturnCart.from_dict(item) + + cart.add_item(return_item) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def remove_cart_item_returns(self, cart_identifier: str, sku_id: SkuId): + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + item = self.redis_client.get_json(look_up_key) + + cart = ReturnCart.from_dict(item) + cart.remove_item(sku_id=sku_id) + self.redis_client.set_json(look_up_key, cart.model_dump()) + return cart + + def get_cart_returns(self, cart_identifier: str): + look_up_key = CartManager.get_lookup_key_returns(cart_identifier) + item = self.redis_client.get_json(look_up_key) + cart = ReturnCart.from_dict(item) + return cart + + +class ReturnsDao: + + def __init__(self): + database_name = os.environ.get("COSMOS_DATABASE_NAME") + collection = "returns" + self.client = CosmosDBUtils(database_name=database_name, collection=collection) + self.search_client = SearchDataAccessObject() + self.cart_manager = CartManager() + + def is_receipt_previously_processed(self, receipt_id: str) -> bool: + + retrieval_sql = "SELECT * FROM c WHERE c.receipt_id = @receipt_id" + query_parameters = [{"name": "@receipt_id", "value": receipt_id}] + items = self.client.query_container(query=retrieval_sql, parameters=query_parameters, enable_cross_partition_query=True) + for retrieved_item in items: + if retrieved_item is not None: + return True + return False + + def get_active_return_skus(self, cart_id: str): + active_return = self.get_cart(cart_identifier=cart_id) + existing_skus: list[SkuId] = [] + for cart_item in active_return.items: + existing_skus.append(cart_item.sku_id) + return existing_skus + + def get_existing_return(self, return_id: str, customer_id: str) -> ReturnTransaction | None: + record_id = return_id + retrieved_record: dict[str, Any] = self.client.get_single_item(item_id=record_id, partition_key=customer_id) + if retrieved_record is not None: + return_record: ReturnTransaction = ReturnTransaction.from_dict(retrieved_record) + return return_record + return None + + def generate_new_cart(self, receipt_id: str, customer_id: str): + return self.cart_manager.generate_new_cart_returns(receipt_id=receipt_id, customer_id=customer_id) + + def create_cart(self, cart_identifier: str, receipt_id: str, customer_id: str): + return self.cart_manager.create_cart_returns(cart_identifier, receipt_id=receipt_id, customer_id=customer_id) + + def add_item(self, cart_identifier: str, sku_id: SkuId, quantity: float): + return self.cart_manager.add_cart_item_returns(cart_identifier=cart_identifier, sku_id=sku_id, quantity=quantity) + + def remove_item(self, cart_identifier: str, sku_id: SkuId): + return self.cart_manager.remove_cart_item_returns(cart_identifier=cart_identifier, sku_id=sku_id) + + def get_cart(self, cart_identifier: str): + cart = self.cart_manager.get_cart_returns(cart_identifier=cart_identifier) + + current_datetime_original: datetime = datetime.now(ZoneInfo("America/New_York")) + current_datetime: str = current_datetime_original.isoformat(timespec="seconds").replace("T", " ") + + return_record = ReturnTransaction(id=cart_identifier, return_id=cart_identifier, receipt_id=cart_identifier, transaction_date=current_datetime, customer_id=cart.customer_id, items=[]) + + for key, value in cart.items.items(): + sku_id: SkuId = key + cart_item: ReturnItem = value + v = self.search_client.get_inventory_levels_by_sku(sku_id=sku_id) + return_item = ReturnItem(sku_id=sku_id, units=cart_item.units, unit_price=v.unit_price) + return_record.items.append(return_item) + + return return_record + + def submit_cart(self, cart_identifier: str): + return_record = self.get_cart(cart_identifier=cart_identifier) + record = return_record.model_dump() + + self.client.upsert_item(record) + return return_record + + +class PurchasesDao: + + def __init__(self): + database_name = os.environ.get("COSMOS_DATABASE_NAME") + collection = "purchases" + self.client = CosmosDBUtils(database_name=database_name, collection=collection) + self.search_client = SearchDataAccessObject() + self.cart_manager = CartManager() + + def get_existing_purchase_sku_quentity(self, receipt_id: str, customer_id: str, sku_id: SkuId) -> float: + existing_purchase = self.get_existing_purchase(receipt_id=receipt_id, customer_id=customer_id) + if existing_purchase is None: + return 0.00 + for purchase_item in existing_purchase.items: + if purchase_item.sku_id == sku_id: + return purchase_item.units + return 0.00 + + def get_existing_purchase_skus(self, receipt_id: str, customer_id: str): + existing_purchase = self.get_existing_purchase(receipt_id=receipt_id, customer_id=customer_id) + existing_skus: list[SkuId] = [] + + if existing_purchase is None: + return existing_skus + + for purchase_item in existing_purchase.items: + existing_skus.append(purchase_item.sku_id) + return existing_skus + + def get_existing_purchase(self, receipt_id: str, customer_id: str) -> Purchase | None: + record_id = receipt_id + retrieved_record: dict[str, Any] = self.client.get_single_item(item_id=record_id, partition_key=customer_id) + if retrieved_record is not None: + purchase: Purchase = Purchase.from_dict(retrieved_record) + return purchase + return None + + def generate_new_cart(self, customer_id: str): + return self.cart_manager.generate_new_cart_purchases(customer_id=customer_id) + + def create_cart(self, cart_identifier: str, customer_id: str): + return self.cart_manager.create_cart_purchases(cart_identifier, customer_id=customer_id) + + def add_item(self, cart_identifier: str, sku_id: SkuId, quantity: float): + self.cart_manager.add_cart_item_purchases(cart_identifier=cart_identifier, sku_id=sku_id, quantity=quantity) + + def remove_item(self, cart_identifier: str, sku_id: SkuId): + self.cart_manager.remove_cart_item_purchases(cart_identifier=cart_identifier, sku_id=sku_id) + + def get_cart(self, cart_identifier: str): + cart = self.cart_manager.get_cart_purchases(cart_identifier=cart_identifier) + + current_datetime_original: datetime = datetime.now(ZoneInfo("America/New_York")) + current_datetime: str = current_datetime_original.isoformat(timespec="seconds").replace("T", " ") + + purchase = Purchase(id=cart_identifier, receipt_id=cart_identifier, + transaction_date=current_datetime, customer_id=cart.customer_id, items=[]) + for key, value in cart.items.items(): + sku_id: SkuId = key + cart_item: PurchaseItem = value + v = self.search_client.get_inventory_levels_by_sku(sku_id=sku_id) + purchase_item = PurchaseItem(sku_id=sku_id, units=cart_item.units, unit_price=v.unit_price, discounts=0) + purchase.items.append(purchase_item) + + return purchase + + def submit_cart(self, cart_identifier: str): + purchase: Purchase = self.get_cart(cart_identifier=cart_identifier) + record = purchase.model_dump() + + self.client.upsert_item(record) + return purchase + + +class ReplenishmentDao: + + def __init__(self): + database_name = os.environ.get("COSMOS_DATABASE_NAME") + collection = "replenishments" + self.client = CosmosDBUtils(database_name=database_name, collection=collection) + self.search_client = SearchDataAccessObject() + self.cart_manager = CartManager() + + def replenish_sku(self, vendor_id: str, sku_id: SkuId, units: float) -> ReplenishmentItem: + current_datetime_original: datetime = datetime.now(ZoneInfo("America/New_York")) + current_datetime: str = current_datetime_original.isoformat(timespec="seconds").replace("T", " ") + + cart_id: int = self.cart_manager.get_cart_id_replenishments() + cart_identifier: str = str(cart_id) + + replenishment_item = ReplenishmentItem(id=cart_identifier, replenishment_id=cart_identifier, + transaction_date=current_datetime, sku_id=sku_id, + units=units, vendor_id=vendor_id) + record = replenishment_item.model_dump() + + self.client.upsert_item(record) + return replenishment_item + + def replenish_department(self, department_id: Departments, vendor_id: str): + + replenishment_results: list[ReplenishmentItem] = [] + dept_replenishment_levels: list[ReplenishmentLevel] = self.search_client.get_replenishment_levels_by_department( + department=department_id) + + for sku_replenishment_level in dept_replenishment_levels: + # This is the current SKU + current_sku_id: SkuId = sku_replenishment_level.sku_id + # This is the Maximum Inventory Level for the SKU + maximum_inventory_level: float = sku_replenishment_level.sku_mil + # The current inventory level for the SKU + current_inventory_level: float = sku_replenishment_level.inventory_level + # How many units we need for replenishment + replenishment_units: float = maximum_inventory_level - current_inventory_level + + if sku_replenishment_level.needs_replenishment: + repl_item = self.replenish_sku(vendor_id=vendor_id, sku_id=current_sku_id, units=replenishment_units) + replenishment_results.append(repl_item) + + return replenishment_results diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py new file mode 100644 index 0000000000..c3e163dc3c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py @@ -0,0 +1,228 @@ +import json +from typing import Mapping, Any, Self, Literal, Union, List + +from pydantic import BaseModel, Field +from .utils import base64_encode + +Departments = Literal["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + +ApplianceId = Literal[ + "101", "102", "103", "104", "105", + "106", "107", "108", "109", "110", + "111", "112", "113", "114", "115", + "116", "117", "118", "119", "120", + "121", "122", "123", "124", "125", +] + +CleaningId = Literal[ + "201", "202", "203", "204", "205", + "206", "207", "208", "209", "210", + "211", "212", "213", "214", "215", + "216", "217", "218", "219", "220", + "221", "222", "223", "224", "225", +] + +DairyId = Literal[ + "301", "302", "303", "304", "305", + "306", "307", "308", "309", "310", + "311", "312", "313", "314", "315", + "316", "317", "318", "319", "320", + "321", "322", "323", "324", "325", +] + +DeliId = Literal[ + "401", "402", "403", "404", "405", + "406", "407", "408", "409", "410", + "411", "412", "413", "414", "415", + "416", "417", "418", "419", "420", + "421", "422", "423", "424", "425", +] + +MeatId = Literal[ + "501", "502", "503", "504", "505", + "506", "507", "508", "509", "510", + "511", "512", "513", "514", "515", + "516", "517", "518", "519", "520", + "521", "522", "523", "524", "525", +] + +PharmacyId = Literal[ + "601", "602", "603", "604", "605", + "606", "607", "608", "609", "610", + "611", "612", "613", "614", "615", + "616", "617", "618", "619", "620", + "621", "622", "623", "624", "625", +] + +ProduceId = Literal[ + "701", "702", "703", "704", "705", + "706", "707", "708", "709", "710", + "711", "712", "713", "714", "715", + "716", "717", "718", "719", "720", + "721", "722", "723", "724", "725", +] + +SeafoodId = Literal[ + "801", "802", "803", "804", "805", + "806", "807", "808", "809", "810", + "811", "812", "813", "814", "815", + "816", "817", "818", "819", "820", + "821", "822", "823", "824", "825", +] + +SkuId = Union[ApplianceId, CleaningId, DairyId, DeliId, MeatId, PharmacyId, ProduceId, SeafoodId] + +class DepartmentInventoryConfig: + + def __init__(self): + + # This is the percentage below which the inventory needs to be replenished + self.replenishment_threshold: float = 0.30 + + # These are maximum inventory levels for each SKU by department + self.mil_config: dict[str, float] = { + "appliance": 200.00, + "cleaning": 200.00, + "dairy": 200.00, + "deli": 50.00, + "meat": 10000.00, + "pharmacy": 50.00, + "produce": 10000.00, + "seafood": 10000.00, + } + + def get_replenishment_threshold(self): + return self.replenishment_threshold + + def get_department_maximum_inventory_level(self, department: Departments) -> float: + return self.mil_config[department] + +class ContosoDataModel(BaseModel): + """Base model that adds a typed `from_dict` constructor for all subclasses.""" + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> Self: + """Converts a python dictionary to a Pydantic object""" + return cls.model_validate(data) + + +class ProductInventory(ContosoDataModel): + sku_id: SkuId = Field(..., description="Unique identifier for the product SKU") + inventory_level: float = Field(..., description="Available inventory quantity for the SKU") + unit_price: float = Field(..., description="Unit price of the product") + name: str = Field(..., description="Name of the product") + description: str = Field(..., description="Detailed description of the product") + department: Departments = Field(..., description="Department where the product belongs") + + def get_lookup_id(self) -> str: + lookup_id = {"sku_id": self.sku_id} + return base64_encode(json.dumps(lookup_id)) + + +class ReplenishmentItem(ContosoDataModel): + id: str = Field(..., description="Unique identifier for the replenishment record") + replenishment_id: str = Field(..., description="Replenishment transaction identifier") + transaction_date: str = Field(..., description="Date and time when stock was replenished") + sku_id: SkuId = Field(..., description="SKU identifier being replenished") + units: float = Field(..., description="Quantity of units replenished") + vendor_id: str = Field(..., description="Unique identifier of the vendor supplying the replenishment") + + +class ReplenishmentLevel(ContosoDataModel): + sku_id: SkuId = Field(..., description="Unique identifier for the product SKU") + sku_mil: float = Field(..., description="The Maximum Inventory Level for the SKU") + inventory_level: float = Field(..., description="Available inventory quantity for the SKU") + needs_replenishment: bool = Field(..., description="Whether or not the SKU needs to be replenished") + name: str = Field(..., description="Name of the product") + description: str = Field(..., description="Detailed description of the product") + department: str = Field(..., description="Department where the product belongs") + + @staticmethod + def from_product_inventory(sku: ProductInventory, config_database: DepartmentInventoryConfig): + sku_mil: float = config_database.get_department_maximum_inventory_level(sku.department) + needs_to_be_replenished: bool = (sku.inventory_level / sku_mil) < config_database.get_replenishment_threshold() + + replenishment_level = ReplenishmentLevel(sku_id=sku.sku_id, sku_mil=sku_mil, + inventory_level=sku.inventory_level, + needs_replenishment=needs_to_be_replenished, + name=sku.name, + description=sku.description, + department=sku.department) + return replenishment_level + + +class NetSales(ContosoDataModel): + sku_id: SkuId = Field(..., description="Unique identifier for the product SKU") + net_sales: float = Field(..., description="Net sales amount for the SKU") + name: str = Field(..., description="Name of the product") + department: str = Field(..., description="Department to which the product belongs") + + def get_lookup_id(self) -> str: + lookup_id = {"sku_id": self.sku_id} + return base64_encode(json.dumps(lookup_id)) + + +class Department(ContosoDataModel): + department: str = Field(..., description="Name of the department") + description: str = Field(..., description="Description of the department's focus or contents") + + def get_lookup_id(self) -> str: + lookup_id = {"department": self.department} + return base64_encode(json.dumps(lookup_id)) + + +class PurchaseItem(ContosoDataModel): + sku_id: SkuId = Field(..., description="Stock Keeping Unit identifier for the product") + units: float = Field(..., description="Number of units purchased") + unit_price: float = Field(..., description="Price per unit at time of transaction") + discounts: float = Field(..., description="Discount applied on the item") + + +class Purchase(ContosoDataModel): + id: str = Field(..., description="Unique transaction identifier") + receipt_id: str = Field(..., description="Receipt identifier") + transaction_date: str = Field(..., description="Date and time of the purchase") + customer_id: str = Field(..., description="Unique customer identifier") + items: List[PurchaseItem] = Field(..., description="List of purchased items") + + +class PurchaseCart(ContosoDataModel): + cart_id: str = Field(..., description="Unique Cart identifier") + customer_id: str = Field(..., description="Unique customer identifier") + items: dict[SkuId, PurchaseItem] = Field(..., description="Map of cart items for each SKU") + + def add_item(self, item: PurchaseItem): + sku_id = item.sku_id + self.items[sku_id] = item + + def remove_item(self, sku_id: SkuId): + return self.items.pop(sku_id, None) + + +class ReturnItem(ContosoDataModel): + sku_id: SkuId = Field(..., description="Stock Keeping Unit identifier") + units: float = Field(..., description="Number of units returned") + unit_price: float = Field(..., description="Original unit price at time of purchase") + + +class ReturnTransaction(ContosoDataModel): + id: str = Field(..., description="Unique transaction identifier for the return record") + return_id: str = Field(..., description="Unique return identifier") + receipt_id: str = Field(..., description="Reference to original purchase receipt") + transaction_date: str = Field(..., description="Date and time of the return") + customer_id: str = Field(..., description="Unique customer identifier") + items: List[ReturnItem] = Field(..., description="List of returned items") + + +class ReturnCart(ContosoDataModel): + cart_id: str = Field(..., description="Unique Cart identifier") + receipt_id: str = Field(..., description="Reference to original purchase receipt") + customer_id: str = Field(..., description="Unique customer identifier") + items: dict[str, ReturnItem] = Field(..., description="Map of cart items for each SKU") + + def add_item(self, item: ReturnItem): + sku_id = item.sku_id + self.items[sku_id] = item + + def remove_item(self, sku_id: SkuId): + return self.items.pop(sku_id, None) diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py new file mode 100644 index 0000000000..79937debf1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py @@ -0,0 +1,97 @@ +from mcp.server import FastMCP + +from . import Department +from . import SearchDataAccessObject +from . import NetSales, ProductInventory, Departments + + +def inventory_service(host: str = "0.0.0.0", port: int = 8080): + + # Declare the MCP service + product_mcp = FastMCP(name="Inventory Service", host=host, port=port) + + @product_mcp.tool(description="Returns a list of all the departments") + async def get_departments() -> list[Department]: + """Retrieve all departments from the database. + + Returns: + list[Department]: A list of `Department` objects. + """ + dao = SearchDataAccessObject() + return dao.get_departments() + + @product_mcp.tool(description="Retrieves the net sales for all the product SKUs") + async def get_net_sales() -> list[NetSales]: + """Retrieves the net sales records from the database. + + Returns: + list[NetSales]: A list of `NetSales` objects sorted by department and SKU. + """ + dao = SearchDataAccessObject() + return dao.get_net_sales() + + @product_mcp.tool(description="Retrieves the net sales amount for a specific SKU") + async def get_net_sales_by_sku(sku_id: str) -> NetSales: + """Retrieve a single net sales record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + NetSales | None: A `NetSales` object if found, otherwise None. + """ + dao = SearchDataAccessObject() + return dao.get_net_sales_by_sku(sku_id=sku_id) + + @product_mcp.tool(description="Retrieves net sales for all the SKUs for the specified department") + async def get_net_sales_by_department(department: Departments): + """Retrieve net sales records filtered by department. + + Args: + department (Departments): The department to filter by. + + Returns: + list[NetSales]: A list of `NetSales` objects for the given department. + """ + dao = SearchDataAccessObject() + return dao.get_net_sales_by_department(department=department) + + @product_mcp.tool(description="Retrieves the inventory level for all the product SKUs") + async def get_inventory_levels() -> list[ProductInventory]: + """Retrieve product inventory levels from the database. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects. + """ + dao = SearchDataAccessObject() + return dao.get_inventory_levels() + + @product_mcp.tool(description="Retrieves the inventory level for product SKUs in the specified department") + async def get_inventory_levels_by_department(department: Departments): + """Retrieve product inventory levels filtered by department. + + Args: + department (Departments): The department to filter by. + + Returns: + list[ProductInventory]: A list of `ProductInventory` objects for the given department. + """ + dao = SearchDataAccessObject() + return dao.get_inventory_levels_by_department(department=department) + + @product_mcp.tool(description="Retrieves the inventory level for the specific product SKU") + async def get_inventory_level_by_sku(sku_id: str): + """Retrieve a single product inventory record by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ProductInventory | None: A `ProductInventory` object if found, otherwise None. + """ + dao = SearchDataAccessObject() + return dao.get_inventory_levels_by_sku(sku_id=sku_id) + + + + return product_mcp \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py new file mode 100644 index 0000000000..ce987cefec --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py @@ -0,0 +1,79 @@ +from mcp.server import FastMCP + +from contoso_retail_application import SearchDataAccessObject, Departments +from contoso_retail_application.data_access_objects import ReplenishmentDao +from contoso_retail_application.models import SkuId, ReplenishmentItem + + +def replenishment_service(host: str = "0.0.0.0", port: int = 8081): + + # Declare the MCP service + replenishment_mcp = FastMCP(name="Replenishment Service", host=host, port=port) + + @replenishment_mcp.tool(description="Returns the replenishment levels for all SKUs") + async def get_replenishment_levels(): + """Retrieve product replenishment levels for all SKUs. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects. + """ + dao = SearchDataAccessObject() + return dao.get_replenishment_levels() + + @replenishment_mcp.tool(description="Returns the replenishment levels for all SKUs for the specified department") + async def get_replenishment_levels_by_department(department: Departments): + """Retrieve product replenishment levels filtered by department. + + Args: + department (Departments): The department to filter by. + + Returns: + list[ReplenishmentLevel]: A list of `ReplenishmentLevel` objects for the given department. + """ + dao = SearchDataAccessObject() + return dao.get_replenishment_levels_by_department(department=department) + + @replenishment_mcp.tool(description="Returns the replenishment level for the specified SKU identifier") + async def get_replenishment_level_by_sku(sku_id: str): + """Retrieve a single product replenishment level by SKU. + + Args: + sku_id (str): The SKU identifier to filter on. + + Returns: + ReplenishmentLevel | None: A `ReplenishmentLevel` object if found, otherwise None. + """ + dao = SearchDataAccessObject() + return dao.get_replenishment_level_by_sku(sku_id=sku_id) + + @replenishment_mcp.tool(description="Replenish the specified SKU identifier") + async def replenish_sku(vendor_id: str, sku_id: SkuId, units: float) -> ReplenishmentItem: + """Replenishes the SKU. + + Args: + vendor_id (str): The vendor identifier. + sku_id (SkuId): The SKU identifier to filter on. + units (float): The number of units of the SKU to replenish. + + Returns: + ReplenishmentItem | None: A `ReplenishmentItem` object if successful, otherwise None. + """ + dao = ReplenishmentDao() + return dao.replenish_sku(vendor_id=vendor_id, sku_id=sku_id, units=units) + + @replenishment_mcp.tool(description="Replenish all the SKUs for the specified department") + async def replenish_department(vendor_id: str, department_id: Departments) ->list[ReplenishmentItem]: + """Replenishes all the SKUs for the department. + + Args: + vendor_id (str): The vendor identifier. + department_id (Departments): The department to replenish + + Returns: + list[ReplenishmentItem]: The items that have been replenished. + """ + dao = ReplenishmentDao() + return dao.replenish_department(vendor_id=vendor_id, department_id=department_id) + + + return replenishment_mcp \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py new file mode 100644 index 0000000000..78d083fbe5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py @@ -0,0 +1,13 @@ +from mcp.server import FastMCP + + +def shopping_service(host: str = "0.0.0.0", port: int = 8082): + + # Declare the MCP service + product_mcp = FastMCP(name="Shopping Service", host=host, port=port) + + @product_mcp.tool(description="Says Hello") + async def say_hello(): + return "Hello" + + return product_mcp \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py new file mode 100644 index 0000000000..b10abb8de9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py @@ -0,0 +1,35 @@ + +class StaticDataset: + + @staticmethod + def get_employee_identifiers() -> list[str]: + employee_ids: list[str] = [ + "james@contosogroceries.ai", + "charlotte@contosogroceries.ai", + "andy@contosogroceries.ai", + "juan@contosogroceries.ai", + "jason@contosogroceries.ai", + "devanshi@contosogroceries.ai" + ] + return employee_ids + + @staticmethod + def get_customer_identifiers() -> list[str]: + customer_ids: list[str] = [ + "angela@contosocustomers.ai", + "patrick@contosocustomers.ai", + "darcy@contosovendors.ai", + "mikhail@contosogroceries.ai", + "jacob@contosogroceries.ai" + ] + return customer_ids + + @staticmethod + def get_vendor_identifiers() -> list[str]: + vendor_ids: list[str] = [ + "seafood@contosovendors.ai", + "meat@contosovendors.ai", + "dairy@contosovendors.ai", + "global@contosovendors.ai" + ] + return vendor_ids diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py new file mode 100644 index 0000000000..f5f9637bdc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py @@ -0,0 +1,9 @@ +import base64 + +def base64_encode(input_value: str) -> str: + encoded_bytes: str = base64.b64encode(input_value.encode("utf-8")).decode("utf-8") + return encoded_bytes + +def base64_decode(encoded_text: str) -> str: + decoded_bytes: str = base64.b64decode(encoded_text.encode("utf-8")).decode('utf-8') + return decoded_bytes diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh new file mode 100644 index 0000000000..5e8e2f96ff --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully +sleep 48h \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh new file mode 100644 index 0000000000..5e8e2f96ff --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully +sleep 48h \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh new file mode 100644 index 0000000000..5e8e2f96ff --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully +sleep 48h \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh new file mode 100644 index 0000000000..a7f7defd34 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully + +# MCP Services for Data CRUD operations +uv run mcp_service.py --service inventory --port 8080 diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh new file mode 100644 index 0000000000..bb713d5ab7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully + +# MCP Services for Data CRUD operations +uv run mcp_service.py --service replenishment --port 8081 diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh new file mode 100644 index 0000000000..a32802eb01 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# This is needed to create (or update) the virtual environment. +# Resolve and install all dependencies listed in pyproject.toml and uv.lock. +# Ensure the environment is in sync with your project metadata. +uv sync + +# Activate the Virtual Environment +source .venv/bin/activate + +# This is needed for Azure AI Search. For some reason, the SSL certs are not working on Macs +# pip install --upgrade certifi +# or +# uv add certifi +PY_CERT=$(python -c "import certifi; print(certifi.where())") + +# make TLS stacks use it +export SSL_CERT_FILE="$PY_CERT" +export REQUESTS_CA_BUNDLE="$PY_CERT" # requests uses this +export AZURE_CA_BUNDLE="$PY_CERT" # Azure SDK honors this + +# Run the application after all of the above are completed successfully + +# MCP Services for Data CRUD operations +uv run mcp_service.py --service shopping --port 8082 diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py new file mode 100644 index 0000000000..ede590ae0f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py @@ -0,0 +1,3 @@ +result = "Hello from Main!!!" + +print(result) diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py new file mode 100644 index 0000000000..df8613df6b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py @@ -0,0 +1,56 @@ +import asyncio +import os +import sys +from argparse import ArgumentParser +from dotenv import load_dotenv + +from contoso_retail_application import inventory_service, replenishment_service, shopping_service + +async def run_mcp_service(): + + service_lists: list[str] = ['shopping', 'replenishment', 'inventory'] + + parser = ArgumentParser(description="Start the MCP service with provided or default configuration.") + + parser.add_argument('--service', required=True, help=f"The name of the service {service_lists}", choices=service_lists) + parser.add_argument('--envFile', required=False, default='.env', help='Path to .env file (default: .env)') + parser.add_argument('--host', required=False, default='0.0.0.0', help='Host IP or name for SSE (default: 0.0.0.0)') + parser.add_argument('--port', required=False, type=int, default=8000, help='Port number for SSE (default: 8000)') + + # Parse the application arguments + args = parser.parse_args() + + # Set up the Host name and port for the service + mcp_service: str = args.service + mcp_host: str = args.host + mcp_port: int = args.port + mcp_env_file: str = args.envFile + + if mcp_service not in service_lists: + parser.print_help() + sys.exit(1) + + # Check if envFile exists and load it + if mcp_env_file and os.path.exists(mcp_env_file): + load_dotenv(dotenv_path=mcp_env_file) + print(f"Environment variables loaded from {mcp_env_file}") + else: + print(f"Env file '{mcp_env_file}' not found. Skipping environment loading.") + + service_dictionary = { + 'inventory' : inventory_service, + 'replenishment': replenishment_service, + 'shopping': shopping_service, + } + + # Pick the service from the dictionary + target_service = service_dictionary[mcp_service] + + # initialize the service + service = target_service(host=mcp_host, port=mcp_port) + + # run the service with the streamable HTTP transport mode + await service.run_streamable_http_async() + +if __name__ == "__main__": + asyncio.run(run_mcp_service()) diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml new file mode 100644 index 0000000000..a9f28e96bc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "contoso-retail-application" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "azure-datastore-utils==0.2.4", + "mcp==1.13.1", + "pydantic-ai==1.0.2", + "pydantic-graph==1.0.2", + "rich>=14.1.0" +] diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py new file mode 100644 index 0000000000..c1055215f2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py @@ -0,0 +1,11 @@ +from contoso_retail_application.data_access_objects import ReplenishmentDao + +dao = ReplenishmentDao() + +result = dao.replenish_sku(vendor_id="israel@a.io", sku_id="101", units=1.00) + +print(result) + + +# This can be run as: +# uv run -m tests.test_replenishment \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py new file mode 100644 index 0000000000..771e83f1cd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py @@ -0,0 +1,11 @@ +from contoso_retail_application import SearchDataAccessObject + +sales = SearchDataAccessObject() + +results = sales.get_net_sales() + +print(results) + + +# This can be run as: +# uv run -m tests.test_sales \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock new file mode 100644 index 0000000000..e54b4d7c6b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock @@ -0,0 +1,2259 @@ +version = 1 +revision = 2 +requires-python = ">=3.12" + +[[package]] +name = "ag-ui-protocol" +version = "0.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/de/0bddf7f26d5f38274c99401735c82ad59df9cead6de42f4bb2ad837286fe/ag_ui_protocol-0.1.8.tar.gz", hash = "sha256:eb745855e9fc30964c77e953890092f8bd7d4bbe6550d6413845428dd0faac0b", size = 5323, upload-time = "2025-07-15T10:55:36.389Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/00/40c6b0313c25d1ab6fac2ecba1cd5b15b1cd3c3a71b3d267ad890e405889/ag_ui_protocol-0.1.8-py3-none-any.whl", hash = "sha256:1567ccb067b7b8158035b941a985e7bb185172d660d4542f3f9c6fff77b55c6e", size = 7066, upload-time = "2025-07-15T10:55:35.075Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.12.15" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/e7/d92a237d8802ca88483906c388f7c201bbe96cd80a165ffd0ac2f6a8d59f/aiohttp-3.12.15.tar.gz", hash = "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", size = 7823716, upload-time = "2025-07-29T05:52:32.215Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/97/77cb2450d9b35f517d6cf506256bf4f5bda3f93a66b4ad64ba7fc917899c/aiohttp-3.12.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", size = 702333, upload-time = "2025-07-29T05:50:46.507Z" }, + { url = "https://files.pythonhosted.org/packages/83/6d/0544e6b08b748682c30b9f65640d006e51f90763b41d7c546693bc22900d/aiohttp-3.12.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", size = 476948, upload-time = "2025-07-29T05:50:48.067Z" }, + { url = "https://files.pythonhosted.org/packages/3a/1d/c8c40e611e5094330284b1aea8a4b02ca0858f8458614fa35754cab42b9c/aiohttp-3.12.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", size = 469787, upload-time = "2025-07-29T05:50:49.669Z" }, + { url = "https://files.pythonhosted.org/packages/38/7d/b76438e70319796bfff717f325d97ce2e9310f752a267bfdf5192ac6082b/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", size = 1716590, upload-time = "2025-07-29T05:50:51.368Z" }, + { url = "https://files.pythonhosted.org/packages/79/b1/60370d70cdf8b269ee1444b390cbd72ce514f0d1cd1a715821c784d272c9/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", size = 1699241, upload-time = "2025-07-29T05:50:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/4968a7b8792437ebc12186db31523f541943e99bda8f30335c482bea6879/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", size = 1754335, upload-time = "2025-07-29T05:50:55.394Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c1/49524ed553f9a0bec1a11fac09e790f49ff669bcd14164f9fab608831c4d/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", size = 1800491, upload-time = "2025-07-29T05:50:57.202Z" }, + { url = "https://files.pythonhosted.org/packages/de/5e/3bf5acea47a96a28c121b167f5ef659cf71208b19e52a88cdfa5c37f1fcc/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", size = 1719929, upload-time = "2025-07-29T05:50:59.192Z" }, + { url = "https://files.pythonhosted.org/packages/39/94/8ae30b806835bcd1cba799ba35347dee6961a11bd507db634516210e91d8/aiohttp-3.12.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", size = 1635733, upload-time = "2025-07-29T05:51:01.394Z" }, + { url = "https://files.pythonhosted.org/packages/7a/46/06cdef71dd03acd9da7f51ab3a9107318aee12ad38d273f654e4f981583a/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", size = 1696790, upload-time = "2025-07-29T05:51:03.657Z" }, + { url = "https://files.pythonhosted.org/packages/02/90/6b4cfaaf92ed98d0ec4d173e78b99b4b1a7551250be8937d9d67ecb356b4/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", size = 1718245, upload-time = "2025-07-29T05:51:05.911Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e6/2593751670fa06f080a846f37f112cbe6f873ba510d070136a6ed46117c6/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", size = 1658899, upload-time = "2025-07-29T05:51:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/8f/28/c15bacbdb8b8eb5bf39b10680d129ea7410b859e379b03190f02fa104ffd/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", size = 1738459, upload-time = "2025-07-29T05:51:09.56Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/c269cbc4faa01fb10f143b1670633a8ddd5b2e1ffd0548f7aa49cb5c70e2/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", size = 1766434, upload-time = "2025-07-29T05:51:11.423Z" }, + { url = "https://files.pythonhosted.org/packages/52/b0/4ff3abd81aa7d929b27d2e1403722a65fc87b763e3a97b3a2a494bfc63bc/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", size = 1726045, upload-time = "2025-07-29T05:51:13.689Z" }, + { url = "https://files.pythonhosted.org/packages/71/16/949225a6a2dd6efcbd855fbd90cf476052e648fb011aa538e3b15b89a57a/aiohttp-3.12.15-cp312-cp312-win32.whl", hash = "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", size = 423591, upload-time = "2025-07-29T05:51:15.452Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d8/fa65d2a349fe938b76d309db1a56a75c4fb8cc7b17a398b698488a939903/aiohttp-3.12.15-cp312-cp312-win_amd64.whl", hash = "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", size = 450266, upload-time = "2025-07-29T05:51:17.239Z" }, + { url = "https://files.pythonhosted.org/packages/f2/33/918091abcf102e39d15aba2476ad9e7bd35ddb190dcdd43a854000d3da0d/aiohttp-3.12.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9f922ffd05034d439dde1c77a20461cf4a1b0831e6caa26151fe7aa8aaebc315", size = 696741, upload-time = "2025-07-29T05:51:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/7495a81e39a998e400f3ecdd44a62107254803d1681d9189be5c2e4530cd/aiohttp-3.12.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ee8a8ac39ce45f3e55663891d4b1d15598c157b4d494a4613e704c8b43112cd", size = 474407, upload-time = "2025-07-29T05:51:21.165Z" }, + { url = "https://files.pythonhosted.org/packages/49/fc/a9576ab4be2dcbd0f73ee8675d16c707cfc12d5ee80ccf4015ba543480c9/aiohttp-3.12.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3eae49032c29d356b94eee45a3f39fdf4b0814b397638c2f718e96cfadf4c4e4", size = 466703, upload-time = "2025-07-29T05:51:22.948Z" }, + { url = "https://files.pythonhosted.org/packages/09/2f/d4bcc8448cf536b2b54eed48f19682031ad182faa3a3fee54ebe5b156387/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97752ff12cc12f46a9b20327104448042fce5c33a624f88c18f66f9368091c7", size = 1705532, upload-time = "2025-07-29T05:51:25.211Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f3/59406396083f8b489261e3c011aa8aee9df360a96ac8fa5c2e7e1b8f0466/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:894261472691d6fe76ebb7fcf2e5870a2ac284c7406ddc95823c8598a1390f0d", size = 1686794, upload-time = "2025-07-29T05:51:27.145Z" }, + { url = "https://files.pythonhosted.org/packages/dc/71/164d194993a8d114ee5656c3b7ae9c12ceee7040d076bf7b32fb98a8c5c6/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fa5d9eb82ce98959fc1031c28198b431b4d9396894f385cb63f1e2f3f20ca6b", size = 1738865, upload-time = "2025-07-29T05:51:29.366Z" }, + { url = "https://files.pythonhosted.org/packages/1c/00/d198461b699188a93ead39cb458554d9f0f69879b95078dce416d3209b54/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fa751efb11a541f57db59c1dd821bec09031e01452b2b6217319b3a1f34f3d", size = 1788238, upload-time = "2025-07-29T05:51:31.285Z" }, + { url = "https://files.pythonhosted.org/packages/85/b8/9e7175e1fa0ac8e56baa83bf3c214823ce250d0028955dfb23f43d5e61fd/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5346b93e62ab51ee2a9d68e8f73c7cf96ffb73568a23e683f931e52450e4148d", size = 1710566, upload-time = "2025-07-29T05:51:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/59/e4/16a8eac9df39b48ae102ec030fa9f726d3570732e46ba0c592aeeb507b93/aiohttp-3.12.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:049ec0360f939cd164ecbfd2873eaa432613d5e77d6b04535e3d1fbae5a9e645", size = 1624270, upload-time = "2025-07-29T05:51:35.195Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/cd84dee7b6ace0740908fd0af170f9fab50c2a41ccbc3806aabcb1050141/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b52dcf013b57464b6d1e51b627adfd69a8053e84b7103a7cd49c030f9ca44461", size = 1677294, upload-time = "2025-07-29T05:51:37.215Z" }, + { url = "https://files.pythonhosted.org/packages/ce/42/d0f1f85e50d401eccd12bf85c46ba84f947a84839c8a1c2c5f6e8ab1eb50/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9b2af240143dd2765e0fb661fd0361a1b469cab235039ea57663cda087250ea9", size = 1708958, upload-time = "2025-07-29T05:51:39.328Z" }, + { url = "https://files.pythonhosted.org/packages/d5/6b/f6fa6c5790fb602538483aa5a1b86fcbad66244997e5230d88f9412ef24c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac77f709a2cde2cc71257ab2d8c74dd157c67a0558a0d2799d5d571b4c63d44d", size = 1651553, upload-time = "2025-07-29T05:51:41.356Z" }, + { url = "https://files.pythonhosted.org/packages/04/36/a6d36ad545fa12e61d11d1932eef273928b0495e6a576eb2af04297fdd3c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:47f6b962246f0a774fbd3b6b7be25d59b06fdb2f164cf2513097998fc6a29693", size = 1727688, upload-time = "2025-07-29T05:51:43.452Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c8/f195e5e06608a97a4e52c5d41c7927301bf757a8e8bb5bbf8cef6c314961/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:760fb7db442f284996e39cf9915a94492e1896baac44f06ae551974907922b64", size = 1761157, upload-time = "2025-07-29T05:51:45.643Z" }, + { url = "https://files.pythonhosted.org/packages/05/6a/ea199e61b67f25ba688d3ce93f63b49b0a4e3b3d380f03971b4646412fc6/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad702e57dc385cae679c39d318def49aef754455f237499d5b99bea4ef582e51", size = 1710050, upload-time = "2025-07-29T05:51:48.203Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2e/ffeb7f6256b33635c29dbed29a22a723ff2dd7401fff42ea60cf2060abfb/aiohttp-3.12.15-cp313-cp313-win32.whl", hash = "sha256:f813c3e9032331024de2eb2e32a88d86afb69291fbc37a3a3ae81cc9917fb3d0", size = 422647, upload-time = "2025-07-29T05:51:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8e/78ee35774201f38d5e1ba079c9958f7629b1fd079459aea9467441dbfbf5/aiohttp-3.12.15-cp313-cp313-win_amd64.whl", hash = "sha256:1a649001580bdb37c6fdb1bebbd7e3bc688e8ec2b5c6f52edbb664662b17dc84", size = 449067, upload-time = "2025-07-29T05:51:52.549Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anthropic" +version = "0.64.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/4f/f2b880cba1a76f3acc7d5eb2ae217632eac1b8cef5ed3027493545c59eba/anthropic-0.64.0.tar.gz", hash = "sha256:3d496c91a63dff64f451b3e8e4b238a9640bf87b0c11d0b74ddc372ba5a3fe58", size = 427893, upload-time = "2025-08-13T17:09:49.915Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/b2/2d268bcd5d6441df9dc0ebebc67107657edb8b0150d3fda1a5b81d1bec45/anthropic-0.64.0-py3-none-any.whl", hash = "sha256:6f5f7d913a6a95eb7f8e1bda4e75f76670e8acd8d4cd965e02e2a256b0429dd1", size = 297244, upload-time = "2025-08-13T17:09:47.908Z" }, +] + +[[package]] +name = "anyio" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, +] + +[[package]] +name = "argcomplete" +version = "3.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/16/0f/861e168fc813c56a78b35f3c30d91c6757d1fd185af1110f1aec784b35d0/argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf", size = 73403, upload-time = "2025-04-03T04:57:03.52Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/da/e42d7a9d8dd33fa775f467e4028a47936da2f01e4b0e561f9ba0d74cb0ca/argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591", size = 43708, upload-time = "2025-04-03T04:57:01.591Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "azure-common" +version = "1.1.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3e/71/f6f71a276e2e69264a97ad39ef850dca0a04fce67b12570730cb38d0ccac/azure-common-1.1.28.zip", hash = "sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3", size = 20914, upload-time = "2022-02-03T19:39:44.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/55/7f118b9c1b23ec15ca05d15a578d8207aa1706bc6f7c87218efffbbf875d/azure_common-1.1.28-py2.py3-none-any.whl", hash = "sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad", size = 14462, upload-time = "2022-02-03T19:39:42.417Z" }, +] + +[[package]] +name = "azure-core" +version = "1.34.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, + { name = "six" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/29/ff7a519a315e41c85bab92a7478c6acd1cf0b14353139a08caee4c691f77/azure_core-1.34.0.tar.gz", hash = "sha256:bdb544989f246a0ad1c85d72eeb45f2f835afdcbc5b45e43f0dbde7461c81ece", size = 297999, upload-time = "2025-05-01T23:17:27.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/9e/5c87b49f65bb16571599bc789857d0ded2f53014d3392bc88a5d1f3ad779/azure_core-1.34.0-py3-none-any.whl", hash = "sha256:0615d3b756beccdb6624d1c0ae97284f38b78fb59a2a9839bf927c66fbbdddd6", size = 207409, upload-time = "2025-05-01T23:17:29.818Z" }, +] + +[[package]] +name = "azure-cosmos" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-core" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/7c/a4e7810f85e7f83d94265ef5ff0fb1efad55a768de737d940151ea2eec45/azure_cosmos-4.9.0.tar.gz", hash = "sha256:c70db4cbf55b0ff261ed7bb8aa325a5dfa565d3c6eaa43d75d26ae5e2ad6d74f", size = 1824155, upload-time = "2024-11-19T04:09:30.195Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/dc/380f843744535497acd0b85aacb59565c84fc28bf938c8d6e897a858cd95/azure_cosmos-4.9.0-py3-none-any.whl", hash = "sha256:3b60eaa01a16a857d0faf0cec304bac6fa8620a81bc268ce760339032ef617fe", size = 303157, upload-time = "2024-11-19T04:09:32.148Z" }, +] + +[[package]] +name = "azure-datastore-utils" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "azure-core" }, + { name = "azure-cosmos" }, + { name = "azure-identity" }, + { name = "azure-search-documents" }, + { name = "certifi" }, + { name = "hatchling" }, + { name = "pydantic" }, + { name = "redis" }, + { name = "redis-entraid" }, + { name = "uv-dynamic-versioning" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/01/d0c7da86dbb0aa6d3dad4fea268d20ecdc7d179f866f13abbe006813ad5c/azure_datastore_utils-0.2.4.tar.gz", hash = "sha256:02be1b710ec5ea39a70f7c3230c77956b74a324397cd8ebac54fe67ab6a4d27a", size = 62875, upload-time = "2025-09-10T21:14:07.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/2f/777e48a8d0946d126610f1f2a950c632bdeb322595c684dcc3d45e3ec60c/azure_datastore_utils-0.2.4-py3-none-any.whl", hash = "sha256:978c31a228ba4d67b1977e438230cdf0f6dc098e16bc8bb194c10d3a42b2cd41", size = 20334, upload-time = "2025-09-10T21:14:06.325Z" }, +] + +[[package]] +name = "azure-identity" +version = "1.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-core" }, + { name = "cryptography" }, + { name = "msal" }, + { name = "msal-extensions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/89/7d170fab0b85d9650cdb7abda087e849644beb52bd28f6804620dd0cecd9/azure_identity-1.20.0.tar.gz", hash = "sha256:40597210d56c83e15031b0fe2ea3b26420189e1e7f3e20bdbb292315da1ba014", size = 264447, upload-time = "2025-02-12T00:40:41.225Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/aa/819513c1dbef990af690bb5eefb5e337f8698d75dfdb7302528f50ce1994/azure_identity-1.20.0-py3-none-any.whl", hash = "sha256:5f23fc4889a66330e840bd78830287e14f3761820fe3c5f77ac875edcb9ec998", size = 188243, upload-time = "2025-02-12T00:40:44.99Z" }, +] + +[[package]] +name = "azure-search-documents" +version = "11.5.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-common" }, + { name = "azure-core" }, + { name = "isodate" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/11/9ecde2bd9e6c00cc0e3f312ab096a33d333f8ba40c847f01f94d524895fe/azure_search_documents-11.5.3.tar.gz", hash = "sha256:6931149ec0db90485d78648407f18ea4271420473c7cb646bf87790374439989", size = 300353, upload-time = "2025-06-25T16:48:58.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/f5/0f6b52567cbb33f1efba13060514ed7088a86de84d74b77cda17d278bcd9/azure_search_documents-11.5.3-py3-none-any.whl", hash = "sha256:110617751c6c8bd50b1f0af2b00a478bd4fbaf4e2f0387e3454c26ec3eb433d6", size = 298772, upload-time = "2025-06-25T16:49:00.764Z" }, +] + +[[package]] +name = "boto3" +version = "1.40.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, + { name = "jmespath" }, + { name = "s3transfer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/b1/0f91a07dc87485a791f2d31df1c2dc75dc5d302fbf002e5446ffa04e8e32/boto3-1.40.17.tar.gz", hash = "sha256:e115dc87d5975d32dfa0ebaf19c39e360665317a350004fa94b03200fe853f2e", size = 112054, upload-time = "2025-08-25T19:37:21.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/b5/1973ed8c107beb2fe5a510d5609603537a4e18a920ead021bed5699c5437/boto3-1.40.17-py3-none-any.whl", hash = "sha256:2cacecd689cb51d81fbf54f84b64d0e6e922fbc18ee513c568b9f61caf4221e0", size = 140076, upload-time = "2025-08-25T19:37:20.087Z" }, +] + +[[package]] +name = "botocore" +version = "1.40.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/87/92b520e7f4ac2a64c6e68bedc1dc3c1335a5aa1efb89a4247b45e34e40ac/botocore-1.40.17.tar.gz", hash = "sha256:769cd04a6a612f2d48b5f456c676fd81733fab682870952f7e2887260ea6a2bc", size = 14375996, upload-time = "2025-08-25T19:37:11.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/fd/bcc913de90d6f0549a04ee40caaf7d4e76efb5a622fc6cc47379f686e50f/botocore-1.40.17-py3-none-any.whl", hash = "sha256:603951935c1a741ae70236bf15725c5293074f28503e7029ad0e24ece476a342", size = 14035937, upload-time = "2025-08-25T19:37:06.75Z" }, +] + +[[package]] +name = "cachetools" +version = "5.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/81/3747dad6b14fa2cf53fcf10548cf5aea6913e96fab41a3c198676f8948a5/cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", size = 28380, upload-time = "2025-02-20T21:01:19.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a", size = 10080, upload-time = "2025-02-20T21:01:16.647Z" }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + +[[package]] +name = "cohere" +version = "5.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastavro" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "pydantic" }, + { name = "pydantic-core" }, + { name = "requests" }, + { name = "tokenizers" }, + { name = "types-requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/ea/0b4bfb4b7f0f445db97acc979308f80ed5ab31df3786b1951d6e48b30d27/cohere-5.17.0.tar.gz", hash = "sha256:70d2fb7bccf8c9de77b07e1c0b3d93accf6346242e3cdc6ce293b577afa74a63", size = 164665, upload-time = "2025-08-13T06:58:00.608Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/21/d0eb7c8e5b3bb748190c59819928c38cafcdf8f8aaca9d21074c64cf1cae/cohere-5.17.0-py3-none-any.whl", hash = "sha256:fe7d8228cda5335a7db79a828893765a4d5a40b7f7a43443736f339dc7813fa4", size = 295301, upload-time = "2025-08-13T06:57:59.072Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "contoso-retail-application" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "azure-datastore-utils" }, + { name = "mcp" }, + { name = "pydantic-ai" }, + { name = "pydantic-graph" }, + { name = "rich" }, +] + +[package.metadata] +requires-dist = [ + { name = "azure-datastore-utils", specifier = "==0.2.4" }, + { name = "mcp", specifier = "==1.13.1" }, + { name = "pydantic-ai", specifier = "==1.0.2" }, + { name = "pydantic-graph", specifier = "==1.0.2" }, + { name = "rich", specifier = ">=14.1.0" }, +] + +[[package]] +name = "cryptography" +version = "45.0.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/0d/d13399c94234ee8f3df384819dc67e0c5ce215fb751d567a55a1f4b028c7/cryptography-45.0.6.tar.gz", hash = "sha256:5c966c732cf6e4a276ce83b6e4c729edda2df6929083a952cc7da973c539c719", size = 744949, upload-time = "2025-08-05T23:59:27.93Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/29/2793d178d0eda1ca4a09a7c4e09a5185e75738cc6d526433e8663b460ea6/cryptography-45.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:048e7ad9e08cf4c0ab07ff7f36cc3115924e22e2266e034450a890d9e312dd74", size = 7042702, upload-time = "2025-08-05T23:58:23.464Z" }, + { url = "https://files.pythonhosted.org/packages/b3/b6/cabd07410f222f32c8d55486c464f432808abaa1f12af9afcbe8f2f19030/cryptography-45.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:44647c5d796f5fc042bbc6d61307d04bf29bccb74d188f18051b635f20a9c75f", size = 4206483, upload-time = "2025-08-05T23:58:27.132Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9e/f9c7d36a38b1cfeb1cc74849aabe9bf817990f7603ff6eb485e0d70e0b27/cryptography-45.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e40b80ecf35ec265c452eea0ba94c9587ca763e739b8e559c128d23bff7ebbbf", size = 4429679, upload-time = "2025-08-05T23:58:29.152Z" }, + { url = "https://files.pythonhosted.org/packages/9c/2a/4434c17eb32ef30b254b9e8b9830cee4e516f08b47fdd291c5b1255b8101/cryptography-45.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:00e8724bdad672d75e6f069b27970883179bd472cd24a63f6e620ca7e41cc0c5", size = 4210553, upload-time = "2025-08-05T23:58:30.596Z" }, + { url = "https://files.pythonhosted.org/packages/ef/1d/09a5df8e0c4b7970f5d1f3aff1b640df6d4be28a64cae970d56c6cf1c772/cryptography-45.0.6-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a3085d1b319d35296176af31c90338eeb2ddac8104661df79f80e1d9787b8b2", size = 3894499, upload-time = "2025-08-05T23:58:32.03Z" }, + { url = "https://files.pythonhosted.org/packages/79/62/120842ab20d9150a9d3a6bdc07fe2870384e82f5266d41c53b08a3a96b34/cryptography-45.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1b7fa6a1c1188c7ee32e47590d16a5a0646270921f8020efc9a511648e1b2e08", size = 4458484, upload-time = "2025-08-05T23:58:33.526Z" }, + { url = "https://files.pythonhosted.org/packages/fd/80/1bc3634d45ddfed0871bfba52cf8f1ad724761662a0c792b97a951fb1b30/cryptography-45.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:275ba5cc0d9e320cd70f8e7b96d9e59903c815ca579ab96c1e37278d231fc402", size = 4210281, upload-time = "2025-08-05T23:58:35.445Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fe/ffb12c2d83d0ee625f124880a1f023b5878f79da92e64c37962bbbe35f3f/cryptography-45.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f4028f29a9f38a2025abedb2e409973709c660d44319c61762202206ed577c42", size = 4456890, upload-time = "2025-08-05T23:58:36.923Z" }, + { url = "https://files.pythonhosted.org/packages/8c/8e/b3f3fe0dc82c77a0deb5f493b23311e09193f2268b77196ec0f7a36e3f3e/cryptography-45.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ee411a1b977f40bd075392c80c10b58025ee5c6b47a822a33c1198598a7a5f05", size = 4333247, upload-time = "2025-08-05T23:58:38.781Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a6/c3ef2ab9e334da27a1d7b56af4a2417d77e7806b2e0f90d6267ce120d2e4/cryptography-45.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e2a21a8eda2d86bb604934b6b37691585bd095c1f788530c1fcefc53a82b3453", size = 4565045, upload-time = "2025-08-05T23:58:40.415Z" }, + { url = "https://files.pythonhosted.org/packages/31/c3/77722446b13fa71dddd820a5faab4ce6db49e7e0bf8312ef4192a3f78e2f/cryptography-45.0.6-cp311-abi3-win32.whl", hash = "sha256:d063341378d7ee9c91f9d23b431a3502fc8bfacd54ef0a27baa72a0843b29159", size = 2928923, upload-time = "2025-08-05T23:58:41.919Z" }, + { url = "https://files.pythonhosted.org/packages/38/63/a025c3225188a811b82932a4dcc8457a26c3729d81578ccecbcce2cb784e/cryptography-45.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:833dc32dfc1e39b7376a87b9a6a4288a10aae234631268486558920029b086ec", size = 3403805, upload-time = "2025-08-05T23:58:43.792Z" }, + { url = "https://files.pythonhosted.org/packages/5b/af/bcfbea93a30809f126d51c074ee0fac5bd9d57d068edf56c2a73abedbea4/cryptography-45.0.6-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:3436128a60a5e5490603ab2adbabc8763613f638513ffa7d311c900a8349a2a0", size = 7020111, upload-time = "2025-08-05T23:58:45.316Z" }, + { url = "https://files.pythonhosted.org/packages/98/c6/ea5173689e014f1a8470899cd5beeb358e22bb3cf5a876060f9d1ca78af4/cryptography-45.0.6-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0d9ef57b6768d9fa58e92f4947cea96ade1233c0e236db22ba44748ffedca394", size = 4198169, upload-time = "2025-08-05T23:58:47.121Z" }, + { url = "https://files.pythonhosted.org/packages/ba/73/b12995edc0c7e2311ffb57ebd3b351f6b268fed37d93bfc6f9856e01c473/cryptography-45.0.6-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea3c42f2016a5bbf71825537c2ad753f2870191134933196bee408aac397b3d9", size = 4421273, upload-time = "2025-08-05T23:58:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/f7/6e/286894f6f71926bc0da67408c853dd9ba953f662dcb70993a59fd499f111/cryptography-45.0.6-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:20ae4906a13716139d6d762ceb3e0e7e110f7955f3bc3876e3a07f5daadec5f3", size = 4199211, upload-time = "2025-08-05T23:58:50.139Z" }, + { url = "https://files.pythonhosted.org/packages/de/34/a7f55e39b9623c5cb571d77a6a90387fe557908ffc44f6872f26ca8ae270/cryptography-45.0.6-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dac5ec199038b8e131365e2324c03d20e97fe214af051d20c49db129844e8b3", size = 3883732, upload-time = "2025-08-05T23:58:52.253Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b9/c6d32edbcba0cd9f5df90f29ed46a65c4631c4fbe11187feb9169c6ff506/cryptography-45.0.6-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:18f878a34b90d688982e43f4b700408b478102dd58b3e39de21b5ebf6509c301", size = 4450655, upload-time = "2025-08-05T23:58:53.848Z" }, + { url = "https://files.pythonhosted.org/packages/77/2d/09b097adfdee0227cfd4c699b3375a842080f065bab9014248933497c3f9/cryptography-45.0.6-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5bd6020c80c5b2b2242d6c48487d7b85700f5e0038e67b29d706f98440d66eb5", size = 4198956, upload-time = "2025-08-05T23:58:55.209Z" }, + { url = "https://files.pythonhosted.org/packages/55/66/061ec6689207d54effdff535bbdf85cc380d32dd5377173085812565cf38/cryptography-45.0.6-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:eccddbd986e43014263eda489abbddfbc287af5cddfd690477993dbb31e31016", size = 4449859, upload-time = "2025-08-05T23:58:56.639Z" }, + { url = "https://files.pythonhosted.org/packages/41/ff/e7d5a2ad2d035e5a2af116e1a3adb4d8fcd0be92a18032917a089c6e5028/cryptography-45.0.6-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:550ae02148206beb722cfe4ef0933f9352bab26b087af00e48fdfb9ade35c5b3", size = 4320254, upload-time = "2025-08-05T23:58:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/82/27/092d311af22095d288f4db89fcaebadfb2f28944f3d790a4cf51fe5ddaeb/cryptography-45.0.6-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5b64e668fc3528e77efa51ca70fadcd6610e8ab231e3e06ae2bab3b31c2b8ed9", size = 4554815, upload-time = "2025-08-05T23:59:00.283Z" }, + { url = "https://files.pythonhosted.org/packages/7e/01/aa2f4940262d588a8fdf4edabe4cda45854d00ebc6eaac12568b3a491a16/cryptography-45.0.6-cp37-abi3-win32.whl", hash = "sha256:780c40fb751c7d2b0c6786ceee6b6f871e86e8718a8ff4bc35073ac353c7cd02", size = 2912147, upload-time = "2025-08-05T23:59:01.716Z" }, + { url = "https://files.pythonhosted.org/packages/0a/bc/16e0276078c2de3ceef6b5a34b965f4436215efac45313df90d55f0ba2d2/cryptography-45.0.6-cp37-abi3-win_amd64.whl", hash = "sha256:20d15aed3ee522faac1a39fbfdfee25d17b1284bafd808e1640a74846d7c4d1b", size = 3390459, upload-time = "2025-08-05T23:59:03.358Z" }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + +[[package]] +name = "dunamai" +version = "1.25.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/2f/194d9a34c4d831c6563d2d990720850f0baef9ab60cb4ad8ae0eff6acd34/dunamai-1.25.0.tar.gz", hash = "sha256:a7f8360ea286d3dbaf0b6a1473f9253280ac93d619836ad4514facb70c0719d1", size = 46155, upload-time = "2025-07-04T19:25:56.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/41/04e2a649058b0713b00d6c9bd22da35618bb157289e05d068e51fddf8d7e/dunamai-1.25.0-py3-none-any.whl", hash = "sha256:7f9dc687dd3256e613b6cc978d9daabfd2bb5deb8adc541fc135ee423ffa98ab", size = 27022, upload-time = "2025-07-04T19:25:54.863Z" }, +] + +[[package]] +name = "eval-type-backport" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/ea/8b0ac4469d4c347c6a385ff09dc3c048c2d021696664e26c7ee6791631b5/eval_type_backport-0.2.2.tar.gz", hash = "sha256:f0576b4cf01ebb5bd358d02314d31846af5e07678387486e2c798af0e7d849c1", size = 9079, upload-time = "2024-12-21T20:09:46.005Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/31/55cd413eaccd39125368be33c46de24a1f639f2e12349b0361b4678f3915/eval_type_backport-0.2.2-py3-none-any.whl", hash = "sha256:cb6ad7c393517f476f96d456d0412ea80f0a8cf96f6892834cd9340149111b0a", size = 5830, upload-time = "2024-12-21T20:09:44.175Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastavro" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/ec/762dcf213e5b97ea1733b27d5a2798599a1fa51565b70a93690246029f84/fastavro-1.12.0.tar.gz", hash = "sha256:a67a87be149825d74006b57e52be068dfa24f3bfc6382543ec92cd72327fe152", size = 1025604, upload-time = "2025-07-31T15:16:42.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/f0/df076a541144d2f351820f3d9e20afa0e4250e6e63cb5a26f94688ed508c/fastavro-1.12.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e849c70198e5bdf6f08df54a68db36ff72bd73e8f14b1fd664323df073c496d8", size = 944288, upload-time = "2025-07-31T15:17:09.756Z" }, + { url = "https://files.pythonhosted.org/packages/52/1d/5c1ea0f6e98a441953de822c7455c9ce8c3afdc7b359dd23c5a5e5039249/fastavro-1.12.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b260e1cdc9a77853a2586b32208302c08dddfb5c20720b5179ac5330e06ce698", size = 3404895, upload-time = "2025-07-31T15:17:11.939Z" }, + { url = "https://files.pythonhosted.org/packages/36/8b/115a3ffe67fb48de0de704284fa5e793afa70932b8b2e915cc7545752f05/fastavro-1.12.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:181779688d8b80957953031f0d82ec0761be667a78e03dac642511ff996c771a", size = 3469935, upload-time = "2025-07-31T15:17:14.145Z" }, + { url = "https://files.pythonhosted.org/packages/14/f8/bf3b7370687ab21205e07b37acdd2455ca69f5d25c72d2b315faf357b1cd/fastavro-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6881caf914b36a57d1f90810f04a89bd9c837dd4a48e1b66a8b92136e85c415d", size = 3306148, upload-time = "2025-07-31T15:17:16.121Z" }, + { url = "https://files.pythonhosted.org/packages/97/55/fba2726b59a984c7aa2fc19c6e8ef1865eca6a3f66e78810d602ca22af59/fastavro-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8bf638248499eb78c422f12fedc08f9b90b5646c3368415e388691db60e7defb", size = 3442851, upload-time = "2025-07-31T15:17:18.738Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3e/25059b8fe0b8084fd858dca77caf0815d73e0ca4731485f34402e8d40c43/fastavro-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ed4f18b7c2f651a5ee2233676f62aac332995086768301aa2c1741859d70b53e", size = 445449, upload-time = "2025-07-31T15:17:20.438Z" }, + { url = "https://files.pythonhosted.org/packages/db/c7/f18b73b39860d54eb724f881b8932882ba10c1d4905e491cd25d159a7e49/fastavro-1.12.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dbe2b690d9caba7d888126cc1dd980a8fcf5ee73de41a104e3f15bb5e08c19c8", size = 936220, upload-time = "2025-07-31T15:17:21.994Z" }, + { url = "https://files.pythonhosted.org/packages/20/22/61ec800fda2a0f051a21b067e4005fd272070132d0a0566c5094e09b666c/fastavro-1.12.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:07ff9e6c6e8739203ccced3205646fdac6141c2efc83f4dffabf5f7d0176646d", size = 3348450, upload-time = "2025-07-31T15:17:24.186Z" }, + { url = "https://files.pythonhosted.org/packages/ca/79/1f34618fb643b99e08853e8a204441ec11a24d3e1fce050e804e6ff5c5ae/fastavro-1.12.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a172655add31882cab4e1a96b7d49f419906b465b4c2165081db7b1db79852f", size = 3417238, upload-time = "2025-07-31T15:17:26.531Z" }, + { url = "https://files.pythonhosted.org/packages/ea/0b/79611769eb15cc17992dc3699141feb0f75afd37b0cb964b4a08be45214e/fastavro-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:be20ce0331b70b35dca1a4c7808afeedf348dc517bd41602ed8fc9a1ac2247a9", size = 3252425, upload-time = "2025-07-31T15:17:28.989Z" }, + { url = "https://files.pythonhosted.org/packages/86/1a/65e0999bcc4bbb38df32706b6ae6ce626d528228667a5e0af059a8b25bb2/fastavro-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a52906681384a18b99b47e5f9eab64b4744d6e6bc91056b7e28641c7b3c59d2b", size = 3385322, upload-time = "2025-07-31T15:17:31.232Z" }, + { url = "https://files.pythonhosted.org/packages/e9/49/c06ebc9e5144f7463c2bfcb900ca01f87db934caf131bccbffc5d0aaf7ec/fastavro-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:cf153531191bcfc445c21e05dd97232a634463aa717cf99fb2214a51b9886bff", size = 445586, upload-time = "2025-07-31T15:17:32.634Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c8/46ab37076dc0f86bb255791baf9b3c3a20f77603a86a40687edacff8c03d/fastavro-1.12.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:1928e88a760688e490118e1bedf0643b1f3727e5ba59c07ac64638dab81ae2a1", size = 1025933, upload-time = "2025-07-31T15:17:34.321Z" }, + { url = "https://files.pythonhosted.org/packages/a9/7f/cb3e069dcc903034a6fe82182d92c75d981d86aee94bd028200a083696b3/fastavro-1.12.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd51b706a3ab3fe4af84a0b37f60d1bcd79295df18932494fc9f49db4ba2bab2", size = 3560435, upload-time = "2025-07-31T15:17:36.314Z" }, + { url = "https://files.pythonhosted.org/packages/d0/12/9478c28a2ac4fcc10ad9488dd3dcd5fac1ef550c3022c57840330e7cec4b/fastavro-1.12.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1148263931f6965e1942cf670f146148ca95b021ae7b7e1f98bf179f1c26cc58", size = 3453000, upload-time = "2025-07-31T15:17:38.875Z" }, + { url = "https://files.pythonhosted.org/packages/00/32/a5c8b3af9561c308c8c27da0be998b6237a47dbbdd8d5499f02731bd4073/fastavro-1.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4099e0f6fb8a55f59891c0aed6bfa90c4d20a774737e5282c74181b4703ea0cb", size = 3383233, upload-time = "2025-07-31T15:17:40.833Z" }, + { url = "https://files.pythonhosted.org/packages/42/a0/f6290f3f8059543faf3ef30efbbe9bf3e4389df881891136cd5fb1066b64/fastavro-1.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:10c586e9e3bab34307f8e3227a2988b6e8ac49bff8f7b56635cf4928a153f464", size = 3402032, upload-time = "2025-07-31T15:17:42.958Z" }, +] + +[[package]] +name = "filelock" +version = "3.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b1/b64018016eeb087db503b038296fd782586432b9c077fc5c7839e9cb6ef6/frozenlist-1.7.0.tar.gz", hash = "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f", size = 45078, upload-time = "2025-06-09T23:02:35.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a2/c8131383f1e66adad5f6ecfcce383d584ca94055a34d683bbb24ac5f2f1c/frozenlist-1.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2", size = 81424, upload-time = "2025-06-09T23:00:42.24Z" }, + { url = "https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb", size = 47952, upload-time = "2025-06-09T23:00:43.481Z" }, + { url = "https://files.pythonhosted.org/packages/01/7a/0046ef1bd6699b40acd2067ed6d6670b4db2f425c56980fa21c982c2a9db/frozenlist-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478", size = 46688, upload-time = "2025-06-09T23:00:44.793Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a2/a910bafe29c86997363fb4c02069df4ff0b5bc39d33c5198b4e9dd42d8f8/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8", size = 243084, upload-time = "2025-06-09T23:00:46.125Z" }, + { url = "https://files.pythonhosted.org/packages/64/3e/5036af9d5031374c64c387469bfcc3af537fc0f5b1187d83a1cf6fab1639/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08", size = 233524, upload-time = "2025-06-09T23:00:47.73Z" }, + { url = "https://files.pythonhosted.org/packages/06/39/6a17b7c107a2887e781a48ecf20ad20f1c39d94b2a548c83615b5b879f28/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4", size = 248493, upload-time = "2025-06-09T23:00:49.742Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/711d1337c7327d88c44d91dd0f556a1c47fb99afc060ae0ef66b4d24793d/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b", size = 244116, upload-time = "2025-06-09T23:00:51.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/fe/74e6ec0639c115df13d5850e75722750adabdc7de24e37e05a40527ca539/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e", size = 224557, upload-time = "2025-06-09T23:00:52.855Z" }, + { url = "https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca", size = 241820, upload-time = "2025-06-09T23:00:54.43Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fa/cb4a76bea23047c8462976ea7b7a2bf53997a0ca171302deae9d6dd12096/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df", size = 236542, upload-time = "2025-06-09T23:00:56.409Z" }, + { url = "https://files.pythonhosted.org/packages/5d/32/476a4b5cfaa0ec94d3f808f193301debff2ea42288a099afe60757ef6282/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5", size = 249350, upload-time = "2025-06-09T23:00:58.468Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ba/9a28042f84a6bf8ea5dbc81cfff8eaef18d78b2a1ad9d51c7bc5b029ad16/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025", size = 225093, upload-time = "2025-06-09T23:01:00.015Z" }, + { url = "https://files.pythonhosted.org/packages/bc/29/3a32959e68f9cf000b04e79ba574527c17e8842e38c91d68214a37455786/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01", size = 245482, upload-time = "2025-06-09T23:01:01.474Z" }, + { url = "https://files.pythonhosted.org/packages/80/e8/edf2f9e00da553f07f5fa165325cfc302dead715cab6ac8336a5f3d0adc2/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08", size = 249590, upload-time = "2025-06-09T23:01:02.961Z" }, + { url = "https://files.pythonhosted.org/packages/1c/80/9a0eb48b944050f94cc51ee1c413eb14a39543cc4f760ed12657a5a3c45a/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43", size = 237785, upload-time = "2025-06-09T23:01:05.095Z" }, + { url = "https://files.pythonhosted.org/packages/f3/74/87601e0fb0369b7a2baf404ea921769c53b7ae00dee7dcfe5162c8c6dbf0/frozenlist-1.7.0-cp312-cp312-win32.whl", hash = "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3", size = 39487, upload-time = "2025-06-09T23:01:06.54Z" }, + { url = "https://files.pythonhosted.org/packages/0b/15/c026e9a9fc17585a9d461f65d8593d281fedf55fbf7eb53f16c6df2392f9/frozenlist-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a", size = 43874, upload-time = "2025-06-09T23:01:07.752Z" }, + { url = "https://files.pythonhosted.org/packages/24/90/6b2cebdabdbd50367273c20ff6b57a3dfa89bd0762de02c3a1eb42cb6462/frozenlist-1.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee", size = 79791, upload-time = "2025-06-09T23:01:09.368Z" }, + { url = "https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d", size = 47165, upload-time = "2025-06-09T23:01:10.653Z" }, + { url = "https://files.pythonhosted.org/packages/f4/25/a0895c99270ca6966110f4ad98e87e5662eab416a17e7fd53c364bf8b954/frozenlist-1.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43", size = 45881, upload-time = "2025-06-09T23:01:12.296Z" }, + { url = "https://files.pythonhosted.org/packages/19/7c/71bb0bbe0832793c601fff68cd0cf6143753d0c667f9aec93d3c323f4b55/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d", size = 232409, upload-time = "2025-06-09T23:01:13.641Z" }, + { url = "https://files.pythonhosted.org/packages/c0/45/ed2798718910fe6eb3ba574082aaceff4528e6323f9a8570be0f7028d8e9/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee", size = 225132, upload-time = "2025-06-09T23:01:15.264Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e2/8417ae0f8eacb1d071d4950f32f229aa6bf68ab69aab797b72a07ea68d4f/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb", size = 237638, upload-time = "2025-06-09T23:01:16.752Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b7/2ace5450ce85f2af05a871b8c8719b341294775a0a6c5585d5e6170f2ce7/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f", size = 233539, upload-time = "2025-06-09T23:01:18.202Z" }, + { url = "https://files.pythonhosted.org/packages/46/b9/6989292c5539553dba63f3c83dc4598186ab2888f67c0dc1d917e6887db6/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60", size = 215646, upload-time = "2025-06-09T23:01:19.649Z" }, + { url = "https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00", size = 232233, upload-time = "2025-06-09T23:01:21.175Z" }, + { url = "https://files.pythonhosted.org/packages/59/52/460db4d7ba0811b9ccb85af996019f5d70831f2f5f255f7cc61f86199795/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b", size = 227996, upload-time = "2025-06-09T23:01:23.098Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/f4b39e904c03927b7ecf891804fd3b4df3db29b9e487c6418e37988d6e9d/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c", size = 242280, upload-time = "2025-06-09T23:01:24.808Z" }, + { url = "https://files.pythonhosted.org/packages/b8/33/3f8d6ced42f162d743e3517781566b8481322be321b486d9d262adf70bfb/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949", size = 217717, upload-time = "2025-06-09T23:01:26.28Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e8/ad683e75da6ccef50d0ab0c2b2324b32f84fc88ceee778ed79b8e2d2fe2e/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca", size = 236644, upload-time = "2025-06-09T23:01:27.887Z" }, + { url = "https://files.pythonhosted.org/packages/b2/14/8d19ccdd3799310722195a72ac94ddc677541fb4bef4091d8e7775752360/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b", size = 238879, upload-time = "2025-06-09T23:01:29.524Z" }, + { url = "https://files.pythonhosted.org/packages/ce/13/c12bf657494c2fd1079a48b2db49fa4196325909249a52d8f09bc9123fd7/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e", size = 232502, upload-time = "2025-06-09T23:01:31.287Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8b/e7f9dfde869825489382bc0d512c15e96d3964180c9499efcec72e85db7e/frozenlist-1.7.0-cp313-cp313-win32.whl", hash = "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1", size = 39169, upload-time = "2025-06-09T23:01:35.503Z" }, + { url = "https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba", size = 43219, upload-time = "2025-06-09T23:01:36.784Z" }, + { url = "https://files.pythonhosted.org/packages/56/d5/5c4cf2319a49eddd9dd7145e66c4866bdc6f3dbc67ca3d59685149c11e0d/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d", size = 84345, upload-time = "2025-06-09T23:01:38.295Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/ec2c1e1dc16b85bc9d526009961953df9cec8481b6886debb36ec9107799/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d", size = 48880, upload-time = "2025-06-09T23:01:39.887Z" }, + { url = "https://files.pythonhosted.org/packages/69/86/f9596807b03de126e11e7d42ac91e3d0b19a6599c714a1989a4e85eeefc4/frozenlist-1.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b", size = 48498, upload-time = "2025-06-09T23:01:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cb/df6de220f5036001005f2d726b789b2c0b65f2363b104bbc16f5be8084f8/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146", size = 292296, upload-time = "2025-06-09T23:01:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/83/1f/de84c642f17c8f851a2905cee2dae401e5e0daca9b5ef121e120e19aa825/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74", size = 273103, upload-time = "2025-06-09T23:01:44.166Z" }, + { url = "https://files.pythonhosted.org/packages/88/3c/c840bfa474ba3fa13c772b93070893c6e9d5c0350885760376cbe3b6c1b3/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1", size = 292869, upload-time = "2025-06-09T23:01:45.681Z" }, + { url = "https://files.pythonhosted.org/packages/a6/1c/3efa6e7d5a39a1d5ef0abeb51c48fb657765794a46cf124e5aca2c7a592c/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1", size = 291467, upload-time = "2025-06-09T23:01:47.234Z" }, + { url = "https://files.pythonhosted.org/packages/4f/00/d5c5e09d4922c395e2f2f6b79b9a20dab4b67daaf78ab92e7729341f61f6/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384", size = 266028, upload-time = "2025-06-09T23:01:48.819Z" }, + { url = "https://files.pythonhosted.org/packages/4e/27/72765be905619dfde25a7f33813ac0341eb6b076abede17a2e3fbfade0cb/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb", size = 284294, upload-time = "2025-06-09T23:01:50.394Z" }, + { url = "https://files.pythonhosted.org/packages/88/67/c94103a23001b17808eb7dd1200c156bb69fb68e63fcf0693dde4cd6228c/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c", size = 281898, upload-time = "2025-06-09T23:01:52.234Z" }, + { url = "https://files.pythonhosted.org/packages/42/34/a3e2c00c00f9e2a9db5653bca3fec306349e71aff14ae45ecc6d0951dd24/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65", size = 290465, upload-time = "2025-06-09T23:01:53.788Z" }, + { url = "https://files.pythonhosted.org/packages/bb/73/f89b7fbce8b0b0c095d82b008afd0590f71ccb3dee6eee41791cf8cd25fd/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3", size = 266385, upload-time = "2025-06-09T23:01:55.769Z" }, + { url = "https://files.pythonhosted.org/packages/cd/45/e365fdb554159462ca12df54bc59bfa7a9a273ecc21e99e72e597564d1ae/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657", size = 288771, upload-time = "2025-06-09T23:01:57.4Z" }, + { url = "https://files.pythonhosted.org/packages/00/11/47b6117002a0e904f004d70ec5194fe9144f117c33c851e3d51c765962d0/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104", size = 288206, upload-time = "2025-06-09T23:01:58.936Z" }, + { url = "https://files.pythonhosted.org/packages/40/37/5f9f3c3fd7f7746082ec67bcdc204db72dad081f4f83a503d33220a92973/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf", size = 282620, upload-time = "2025-06-09T23:02:00.493Z" }, + { url = "https://files.pythonhosted.org/packages/0b/31/8fbc5af2d183bff20f21aa743b4088eac4445d2bb1cdece449ae80e4e2d1/frozenlist-1.7.0-cp313-cp313t-win32.whl", hash = "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81", size = 43059, upload-time = "2025-06-09T23:02:02.072Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ed/41956f52105b8dbc26e457c5705340c67c8cc2b79f394b79bffc09d0e938/frozenlist-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e", size = 47516, upload-time = "2025-06-09T23:02:03.779Z" }, + { url = "https://files.pythonhosted.org/packages/ee/45/b82e3c16be2182bff01179db177fe144d58b5dc787a7d4492c6ed8b9317f/frozenlist-1.7.0-py3-none-any.whl", hash = "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e", size = 13106, upload-time = "2025-06-09T23:02:34.204Z" }, +] + +[[package]] +name = "fsspec" +version = "2025.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/02/0835e6ab9cfc03916fe3f78c0956cfcdb6ff2669ffa6651065d5ebf7fc98/fsspec-2025.7.0.tar.gz", hash = "sha256:786120687ffa54b8283d942929540d8bc5ccfa820deb555a2b5d0ed2b737bf58", size = 304432, upload-time = "2025-07-15T16:05:21.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/e0/014d5d9d7a4564cf1c40b5039bc882db69fd881111e03ab3657ac0b218e2/fsspec-2025.7.0-py3-none-any.whl", hash = "sha256:8b012e39f63c7d5f10474de957f3ab793b47b45ae7d39f2fb735f8bbe25c0e21", size = 199597, upload-time = "2025-07-15T16:05:19.529Z" }, +] + +[[package]] +name = "genai-prices" +version = "0.0.24" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/3d/59c5d4d83999acb09e3c8062e34a73969db88d18353d55b3eed495d32921/genai_prices-0.0.24.tar.gz", hash = "sha256:faeac6276964bc31ca9a2551219d4642979426bd2c593e884ec5bb40089b298e", size = 44702, upload-time = "2025-08-26T12:12:57.476Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/d4/48ec6b327c2ba8c381a10484dd97f15e6b51a1ea708dc783e71fc5e01234/genai_prices-0.0.24-py3-none-any.whl", hash = "sha256:620beb35a845b32463201bb2816060181500e15c0a715b3bfa2583ef58e0702d", size = 47028, upload-time = "2025-08-26T12:12:56.162Z" }, +] + +[[package]] +name = "google-auth" +version = "2.40.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachetools" }, + { name = "pyasn1-modules" }, + { name = "rsa" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/9b/e92ef23b84fa10a64ce4831390b7a4c2e53c0132568d99d4ae61d04c8855/google_auth-2.40.3.tar.gz", hash = "sha256:500c3a29adedeb36ea9cf24b8d10858e152f2412e3ca37829b3fa18e33d63b77", size = 281029, upload-time = "2025-06-04T18:04:57.577Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/63/b19553b658a1692443c62bd07e5868adaa0ad746a0751ba62c59568cd45b/google_auth-2.40.3-py2.py3-none-any.whl", hash = "sha256:1370d4593e86213563547f97a92752fc658456fe4514c809544f330fed45a7ca", size = 216137, upload-time = "2025-06-04T18:04:55.573Z" }, +] + +[[package]] +name = "google-genai" +version = "1.31.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "google-auth" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/1b/da30fa6e2966942d7028a58eb7aa7d04544dcc3aa66194365b2e0adac570/google_genai-1.31.0.tar.gz", hash = "sha256:8572b47aa684357c3e5e10d290ec772c65414114939e3ad2955203e27cd2fcbc", size = 233482, upload-time = "2025-08-18T23:40:21.733Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/27/1525bc9cbec58660f0842ebcbfe910a1dde908c2672373804879666e0bb8/google_genai-1.31.0-py3-none-any.whl", hash = "sha256:5c6959bcf862714e8ed0922db3aaf41885bacf6318751b3421bf1e459f78892f", size = 231876, upload-time = "2025-08-18T23:40:20.385Z" }, +] + +[[package]] +name = "googleapis-common-protos" +version = "1.70.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903, upload-time = "2025-04-14T10:17:02.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" }, +] + +[[package]] +name = "griffe" +version = "1.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/b5/23b91f22b7b3a7f8f62223f6664946271c0f5cb4179605a3e6bbae863920/griffe-1.13.0.tar.gz", hash = "sha256:246ea436a5e78f7fbf5f24ca8a727bb4d2a4b442a2959052eea3d0bfe9a076e0", size = 412759, upload-time = "2025-08-26T13:27:11.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/8c/b7cfdd8dfe48f6b09f7353323732e1a290c388bd14f216947928dc85f904/griffe-1.13.0-py3-none-any.whl", hash = "sha256:470fde5b735625ac0a36296cd194617f039e9e83e301fcbd493e2b58382d0559", size = 139365, upload-time = "2025-08-26T13:27:09.882Z" }, +] + +[[package]] +name = "groq" +version = "0.31.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/a2/77fd1460e7d55859219223719aa44ae8902a3a1ad333cd5faf330eb0b894/groq-0.31.0.tar.gz", hash = "sha256:182252e9bf0d696df607c137cbafa851d2c84aaf94bcfe9165c0bc231043490c", size = 136237, upload-time = "2025-08-05T23:14:01.183Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/f8/14672d69a91495f43462c5490067eeafc30346e81bda1a62848e897f9bc3/groq-0.31.0-py3-none-any.whl", hash = "sha256:5e3c7ec9728b7cccf913da982a9b5ebb46dc18a070b35e12a3d6a1e12d6b0f7f", size = 131365, upload-time = "2025-08-05T23:13:59.768Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "hatchling" +version = "1.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "pathspec" }, + { name = "pluggy" }, + { name = "trove-classifiers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/8a/cc1debe3514da292094f1c3a700e4ca25442489731ef7c0814358816bb03/hatchling-1.27.0.tar.gz", hash = "sha256:971c296d9819abb3811112fc52c7a9751c8d381898f36533bb16f9791e941fd6", size = 54983, upload-time = "2024-12-15T17:08:11.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/e7/ae38d7a6dfba0533684e0b2136817d667588ae3ec984c1a4e5df5eb88482/hatchling-1.27.0-py3-none-any.whl", hash = "sha256:d3a2f3567c4f926ea39849cdf924c7e99e6686c9c8e288ae1037c8fa2a5d937b", size = 75794, upload-time = "2024-12-15T17:08:10.364Z" }, +] + +[[package]] +name = "hf-xet" +version = "1.1.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/49/91010b59debc7c862a5fd426d343134dd9a68778dbe570234b6495a4e204/hf_xet-1.1.8.tar.gz", hash = "sha256:62a0043e441753bbc446dcb5a3fe40a4d03f5fb9f13589ef1df9ab19252beb53", size = 484065, upload-time = "2025-08-18T22:01:03.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/91/5814db3a0d4a65fb6a87f0931ae28073b87f06307701fe66e7c41513bfb4/hf_xet-1.1.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3d5f82e533fc51c7daad0f9b655d9c7811b5308e5890236828bd1dd3ed8fea74", size = 2752357, upload-time = "2025-08-18T22:00:58.777Z" }, + { url = "https://files.pythonhosted.org/packages/70/72/ce898516e97341a7a9d450609e130e108643389110261eaee6deb1ba8545/hf_xet-1.1.8-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:8e2dba5896bca3ab61d0bef4f01a1647004de59640701b37e37eaa57087bbd9d", size = 2613142, upload-time = "2025-08-18T22:00:57.252Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d6/13af5f916cef795ac2b5e4cc1de31f2e0e375f4475d50799915835f301c2/hf_xet-1.1.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfe5700bc729be3d33d4e9a9b5cc17a951bf8c7ada7ba0c9198a6ab2053b7453", size = 3175859, upload-time = "2025-08-18T22:00:55.978Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ed/34a193c9d1d72b7c3901b3b5153b1be9b2736b832692e1c3f167af537102/hf_xet-1.1.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:09e86514c3c4284ed8a57d6b0f3d089f9836a0af0a1ceb3c9dd664f1f3eaefef", size = 3074178, upload-time = "2025-08-18T22:00:54.147Z" }, + { url = "https://files.pythonhosted.org/packages/4a/1b/de6817b4bf65385280252dff5c9cceeedfbcb27ddb93923639323c1034a4/hf_xet-1.1.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4a9b99ab721d385b83f4fc8ee4e0366b0b59dce03b5888a86029cc0ca634efbf", size = 3238122, upload-time = "2025-08-18T22:01:00.546Z" }, + { url = "https://files.pythonhosted.org/packages/b7/13/874c85c7ed519ec101deb654f06703d9e5e68d34416730f64c4755ada36a/hf_xet-1.1.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25b9d43333bbef39aeae1616789ec329c21401a7fe30969d538791076227b591", size = 3344325, upload-time = "2025-08-18T22:01:02.013Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/0aaf279f4f3dea58e99401b92c31c0f752924ba0e6c7d7bb07b1dbd7f35e/hf_xet-1.1.8-cp37-abi3-win_amd64.whl", hash = "sha256:4171f31d87b13da4af1ed86c98cf763292e4720c088b4957cf9d564f92904ca9", size = 2801689, upload-time = "2025-08-18T22:01:04.81Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624, upload-time = "2023-12-22T08:01:21.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819, upload-time = "2023-12-22T08:01:19.89Z" }, +] + +[[package]] +name = "huggingface-hub" +version = "0.34.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "hf-xet", marker = "platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/c9/bdbe19339f76d12985bc03572f330a01a93c04dffecaaea3061bdd7fb892/huggingface_hub-0.34.4.tar.gz", hash = "sha256:a4228daa6fb001be3f4f4bdaf9a0db00e1739235702848df00885c9b5742c85c", size = 459768, upload-time = "2025-08-08T09:14:52.365Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/7b/bb06b061991107cd8783f300adff3e7b7f284e330fd82f507f2a1417b11d/huggingface_hub-0.34.4-py3-none-any.whl", hash = "sha256:9b365d781739c93ff90c359844221beef048403f1bc1f1c123c191257c3c890a", size = 561452, upload-time = "2025-08-08T09:14:50.159Z" }, +] + +[package.optional-dependencies] +inference = [ + { name = "aiohttp" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, +] + +[[package]] +name = "invoke" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/42/127e6d792884ab860defc3f4d80a8f9812e48ace584ffc5a346de58cdc6c/invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5", size = 299835, upload-time = "2023-07-12T18:05:17.998Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/66/7f8c48009c72d73bc6bbe6eb87ac838d6a526146f7dab14af671121eb379/invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820", size = 160274, upload-time = "2023-07-12T18:05:16.294Z" }, +] + +[[package]] +name = "isodate" +version = "0.7.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705, upload-time = "2024-10-08T23:04:11.5Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jiter" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/9d/ae7ddb4b8ab3fb1b51faf4deb36cb48a4fbbd7cb36bad6a5fca4741306f7/jiter-0.10.0.tar.gz", hash = "sha256:07a7142c38aacc85194391108dc91b5b57093c978a9932bd86a36862759d9500", size = 162759, upload-time = "2025-05-18T19:04:59.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/b5/348b3313c58f5fbfb2194eb4d07e46a35748ba6e5b3b3046143f3040bafa/jiter-0.10.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1e274728e4a5345a6dde2d343c8da018b9d4bd4350f5a472fa91f66fda44911b", size = 312262, upload-time = "2025-05-18T19:03:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/9c/4a/6a2397096162b21645162825f058d1709a02965606e537e3304b02742e9b/jiter-0.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7202ae396446c988cb2a5feb33a543ab2165b786ac97f53b59aafb803fef0744", size = 320124, upload-time = "2025-05-18T19:03:46.341Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/1ce02cade7516b726dd88f59a4ee46914bf79d1676d1228ef2002ed2f1c9/jiter-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23ba7722d6748b6920ed02a8f1726fb4b33e0fd2f3f621816a8b486c66410ab2", size = 345330, upload-time = "2025-05-18T19:03:47.596Z" }, + { url = "https://files.pythonhosted.org/packages/75/d0/bb6b4f209a77190ce10ea8d7e50bf3725fc16d3372d0a9f11985a2b23eff/jiter-0.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:371eab43c0a288537d30e1f0b193bc4eca90439fc08a022dd83e5e07500ed026", size = 369670, upload-time = "2025-05-18T19:03:49.334Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f5/a61787da9b8847a601e6827fbc42ecb12be2c925ced3252c8ffcb56afcaf/jiter-0.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c675736059020365cebc845a820214765162728b51ab1e03a1b7b3abb70f74c", size = 489057, upload-time = "2025-05-18T19:03:50.66Z" }, + { url = "https://files.pythonhosted.org/packages/12/e4/6f906272810a7b21406c760a53aadbe52e99ee070fc5c0cb191e316de30b/jiter-0.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c5867d40ab716e4684858e4887489685968a47e3ba222e44cde6e4a2154f959", size = 389372, upload-time = "2025-05-18T19:03:51.98Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ba/77013b0b8ba904bf3762f11e0129b8928bff7f978a81838dfcc958ad5728/jiter-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395bb9a26111b60141757d874d27fdea01b17e8fac958b91c20128ba8f4acc8a", size = 352038, upload-time = "2025-05-18T19:03:53.703Z" }, + { url = "https://files.pythonhosted.org/packages/67/27/c62568e3ccb03368dbcc44a1ef3a423cb86778a4389e995125d3d1aaa0a4/jiter-0.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6842184aed5cdb07e0c7e20e5bdcfafe33515ee1741a6835353bb45fe5d1bd95", size = 391538, upload-time = "2025-05-18T19:03:55.046Z" }, + { url = "https://files.pythonhosted.org/packages/c0/72/0d6b7e31fc17a8fdce76164884edef0698ba556b8eb0af9546ae1a06b91d/jiter-0.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62755d1bcea9876770d4df713d82606c8c1a3dca88ff39046b85a048566d56ea", size = 523557, upload-time = "2025-05-18T19:03:56.386Z" }, + { url = "https://files.pythonhosted.org/packages/2f/09/bc1661fbbcbeb6244bd2904ff3a06f340aa77a2b94e5a7373fd165960ea3/jiter-0.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533efbce2cacec78d5ba73a41756beff8431dfa1694b6346ce7af3a12c42202b", size = 514202, upload-time = "2025-05-18T19:03:57.675Z" }, + { url = "https://files.pythonhosted.org/packages/1b/84/5a5d5400e9d4d54b8004c9673bbe4403928a00d28529ff35b19e9d176b19/jiter-0.10.0-cp312-cp312-win32.whl", hash = "sha256:8be921f0cadd245e981b964dfbcd6fd4bc4e254cdc069490416dd7a2632ecc01", size = 211781, upload-time = "2025-05-18T19:03:59.025Z" }, + { url = "https://files.pythonhosted.org/packages/9b/52/7ec47455e26f2d6e5f2ea4951a0652c06e5b995c291f723973ae9e724a65/jiter-0.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7c7d785ae9dda68c2678532a5a1581347e9c15362ae9f6e68f3fdbfb64f2e49", size = 206176, upload-time = "2025-05-18T19:04:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b0/279597e7a270e8d22623fea6c5d4eeac328e7d95c236ed51a2b884c54f70/jiter-0.10.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e0588107ec8e11b6f5ef0e0d656fb2803ac6cf94a96b2b9fc675c0e3ab5e8644", size = 311617, upload-time = "2025-05-18T19:04:02.078Z" }, + { url = "https://files.pythonhosted.org/packages/91/e3/0916334936f356d605f54cc164af4060e3e7094364add445a3bc79335d46/jiter-0.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cafc4628b616dc32530c20ee53d71589816cf385dd9449633e910d596b1f5c8a", size = 318947, upload-time = "2025-05-18T19:04:03.347Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8e/fd94e8c02d0e94539b7d669a7ebbd2776e51f329bb2c84d4385e8063a2ad/jiter-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:520ef6d981172693786a49ff5b09eda72a42e539f14788124a07530f785c3ad6", size = 344618, upload-time = "2025-05-18T19:04:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/6f/b0/f9f0a2ec42c6e9c2e61c327824687f1e2415b767e1089c1d9135f43816bd/jiter-0.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:554dedfd05937f8fc45d17ebdf298fe7e0c77458232bcb73d9fbbf4c6455f5b3", size = 368829, upload-time = "2025-05-18T19:04:06.912Z" }, + { url = "https://files.pythonhosted.org/packages/e8/57/5bbcd5331910595ad53b9fd0c610392ac68692176f05ae48d6ce5c852967/jiter-0.10.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bc299da7789deacf95f64052d97f75c16d4fc8c4c214a22bf8d859a4288a1c2", size = 491034, upload-time = "2025-05-18T19:04:08.222Z" }, + { url = "https://files.pythonhosted.org/packages/9b/be/c393df00e6e6e9e623a73551774449f2f23b6ec6a502a3297aeeece2c65a/jiter-0.10.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5161e201172de298a8a1baad95eb85db4fb90e902353b1f6a41d64ea64644e25", size = 388529, upload-time = "2025-05-18T19:04:09.566Z" }, + { url = "https://files.pythonhosted.org/packages/42/3e/df2235c54d365434c7f150b986a6e35f41ebdc2f95acea3036d99613025d/jiter-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e2227db6ba93cb3e2bf67c87e594adde0609f146344e8207e8730364db27041", size = 350671, upload-time = "2025-05-18T19:04:10.98Z" }, + { url = "https://files.pythonhosted.org/packages/c6/77/71b0b24cbcc28f55ab4dbfe029f9a5b73aeadaba677843fc6dc9ed2b1d0a/jiter-0.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15acb267ea5e2c64515574b06a8bf393fbfee6a50eb1673614aa45f4613c0cca", size = 390864, upload-time = "2025-05-18T19:04:12.722Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d3/ef774b6969b9b6178e1d1e7a89a3bd37d241f3d3ec5f8deb37bbd203714a/jiter-0.10.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:901b92f2e2947dc6dfcb52fd624453862e16665ea909a08398dde19c0731b7f4", size = 522989, upload-time = "2025-05-18T19:04:14.261Z" }, + { url = "https://files.pythonhosted.org/packages/0c/41/9becdb1d8dd5d854142f45a9d71949ed7e87a8e312b0bede2de849388cb9/jiter-0.10.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d0cb9a125d5a3ec971a094a845eadde2db0de85b33c9f13eb94a0c63d463879e", size = 513495, upload-time = "2025-05-18T19:04:15.603Z" }, + { url = "https://files.pythonhosted.org/packages/9c/36/3468e5a18238bdedae7c4d19461265b5e9b8e288d3f86cd89d00cbb48686/jiter-0.10.0-cp313-cp313-win32.whl", hash = "sha256:48a403277ad1ee208fb930bdf91745e4d2d6e47253eedc96e2559d1e6527006d", size = 211289, upload-time = "2025-05-18T19:04:17.541Z" }, + { url = "https://files.pythonhosted.org/packages/7e/07/1c96b623128bcb913706e294adb5f768fb7baf8db5e1338ce7b4ee8c78ef/jiter-0.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:75f9eb72ecb640619c29bf714e78c9c46c9c4eaafd644bf78577ede459f330d4", size = 205074, upload-time = "2025-05-18T19:04:19.21Z" }, + { url = "https://files.pythonhosted.org/packages/54/46/caa2c1342655f57d8f0f2519774c6d67132205909c65e9aa8255e1d7b4f4/jiter-0.10.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:28ed2a4c05a1f32ef0e1d24c2611330219fed727dae01789f4a335617634b1ca", size = 318225, upload-time = "2025-05-18T19:04:20.583Z" }, + { url = "https://files.pythonhosted.org/packages/43/84/c7d44c75767e18946219ba2d703a5a32ab37b0bc21886a97bc6062e4da42/jiter-0.10.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a4c418b1ec86a195f1ca69da8b23e8926c752b685af665ce30777233dfe070", size = 350235, upload-time = "2025-05-18T19:04:22.363Z" }, + { url = "https://files.pythonhosted.org/packages/01/16/f5a0135ccd968b480daad0e6ab34b0c7c5ba3bc447e5088152696140dcb3/jiter-0.10.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d7bfed2fe1fe0e4dda6ef682cee888ba444b21e7a6553e03252e4feb6cf0adca", size = 207278, upload-time = "2025-05-18T19:04:23.627Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9b/1d646da42c3de6c2188fdaa15bce8ecb22b635904fc68be025e21249ba44/jiter-0.10.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:5e9251a5e83fab8d87799d3e1a46cb4b7f2919b895c6f4483629ed2446f66522", size = 310866, upload-time = "2025-05-18T19:04:24.891Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0e/26538b158e8a7c7987e94e7aeb2999e2e82b1f9d2e1f6e9874ddf71ebda0/jiter-0.10.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:023aa0204126fe5b87ccbcd75c8a0d0261b9abdbbf46d55e7ae9f8e22424eeb8", size = 318772, upload-time = "2025-05-18T19:04:26.161Z" }, + { url = "https://files.pythonhosted.org/packages/7b/fb/d302893151caa1c2636d6574d213e4b34e31fd077af6050a9c5cbb42f6fb/jiter-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c189c4f1779c05f75fc17c0c1267594ed918996a231593a21a5ca5438445216", size = 344534, upload-time = "2025-05-18T19:04:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/01/d8/5780b64a149d74e347c5128d82176eb1e3241b1391ac07935693466d6219/jiter-0.10.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15720084d90d1098ca0229352607cd68256c76991f6b374af96f36920eae13c4", size = 369087, upload-time = "2025-05-18T19:04:28.896Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5b/f235a1437445160e777544f3ade57544daf96ba7e96c1a5b24a6f7ac7004/jiter-0.10.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4f2fb68e5f1cfee30e2b2a09549a00683e0fde4c6a2ab88c94072fc33cb7426", size = 490694, upload-time = "2025-05-18T19:04:30.183Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/9c3d4617caa2ff89cf61b41e83820c27ebb3f7b5fae8a72901e8cd6ff9be/jiter-0.10.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce541693355fc6da424c08b7edf39a2895f58d6ea17d92cc2b168d20907dee12", size = 388992, upload-time = "2025-05-18T19:04:32.028Z" }, + { url = "https://files.pythonhosted.org/packages/68/b1/344fd14049ba5c94526540af7eb661871f9c54d5f5601ff41a959b9a0bbd/jiter-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31c50c40272e189d50006ad5c73883caabb73d4e9748a688b216e85a9a9ca3b9", size = 351723, upload-time = "2025-05-18T19:04:33.467Z" }, + { url = "https://files.pythonhosted.org/packages/41/89/4c0e345041186f82a31aee7b9d4219a910df672b9fef26f129f0cda07a29/jiter-0.10.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fa3402a2ff9815960e0372a47b75c76979d74402448509ccd49a275fa983ef8a", size = 392215, upload-time = "2025-05-18T19:04:34.827Z" }, + { url = "https://files.pythonhosted.org/packages/55/58/ee607863e18d3f895feb802154a2177d7e823a7103f000df182e0f718b38/jiter-0.10.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:1956f934dca32d7bb647ea21d06d93ca40868b505c228556d3373cbd255ce853", size = 522762, upload-time = "2025-05-18T19:04:36.19Z" }, + { url = "https://files.pythonhosted.org/packages/15/d0/9123fb41825490d16929e73c212de9a42913d68324a8ce3c8476cae7ac9d/jiter-0.10.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:fcedb049bdfc555e261d6f65a6abe1d5ad68825b7202ccb9692636c70fcced86", size = 513427, upload-time = "2025-05-18T19:04:37.544Z" }, + { url = "https://files.pythonhosted.org/packages/d8/b3/2bd02071c5a2430d0b70403a34411fc519c2f227da7b03da9ba6a956f931/jiter-0.10.0-cp314-cp314-win32.whl", hash = "sha256:ac509f7eccca54b2a29daeb516fb95b6f0bd0d0d8084efaf8ed5dfc7b9f0b357", size = 210127, upload-time = "2025-05-18T19:04:38.837Z" }, + { url = "https://files.pythonhosted.org/packages/03/0c/5fe86614ea050c3ecd728ab4035534387cd41e7c1855ef6c031f1ca93e3f/jiter-0.10.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5ed975b83a2b8639356151cef5c0d597c68376fc4922b45d0eb384ac058cfa00", size = 318527, upload-time = "2025-05-18T19:04:40.612Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4a/4175a563579e884192ba6e81725fc0448b042024419be8d83aa8a80a3f44/jiter-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa96f2abba33dc77f79b4cf791840230375f9534e5fac927ccceb58c5e604a5", size = 354213, upload-time = "2025-05-18T19:04:41.894Z" }, +] + +[[package]] +name = "jmespath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bf/ce/46fbd9c8119cfc3581ee5643ea49464d168028cfb5caff5fc0596d0cf914/jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608", size = 15513, upload-time = "2025-04-23T12:34:07.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" }, +] + +[[package]] +name = "logfire" +version = "4.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "executing" }, + { name = "opentelemetry-exporter-otlp-proto-http" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-sdk" }, + { name = "protobuf" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/fa/14cbd976e8ff77290c0c87f93c45029785537ffb84e2f5215416786cda11/logfire-4.6.0.tar.gz", hash = "sha256:974bc8f4efd3aa9df2d0c7b1d53b35dc4612ff5cee2be6c40dd65e5c26eab694", size = 533174, upload-time = "2025-09-10T14:56:42.168Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/9c/6384dc69601bfba19c1f5909a472b00cc4b5863f411ecf85be308beacf8f/logfire-4.6.0-py3-none-any.whl", hash = "sha256:d322844db7a2f1935976f2852a07e3753489ecc4e83fa288173b05a453bb1cbf", size = 219556, upload-time = "2025-09-10T14:56:37.278Z" }, +] + +[package.optional-dependencies] +httpx = [ + { name = "opentelemetry-instrumentation-httpx" }, +] + +[[package]] +name = "logfire-api" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/99/130ff82b2eed7856b7192d3a948071e519eff58f777ad5fb49a44e8953c1/logfire_api-4.3.6.tar.gz", hash = "sha256:c07e4fa165e15f0b22e5ff39c0253b48dc9a4b42ab574fb0d63eb40050c07ae1", size = 52914, upload-time = "2025-08-26T07:59:28.627Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/e8/b830d18f680e70215ba6cd150a335954f82fd86d65003902c133d8f14aa0/logfire_api-4.3.6-py3-none-any.whl", hash = "sha256:40c190d4aaca1d223bf1e312adda274288ea9267b6e9c4e6c1a896a14c006eed", size = 88495, upload-time = "2025-08-26T07:59:24.953Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, +] + +[[package]] +name = "mcp" +version = "1.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/3c/82c400c2d50afdac4fbefb5b4031fd327e2ad1f23ccef8eee13c5909aa48/mcp-1.13.1.tar.gz", hash = "sha256:165306a8fd7991dc80334edd2de07798175a56461043b7ae907b279794a834c5", size = 438198, upload-time = "2025-08-22T09:22:16.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/3f/d085c7f49ade6d273b185d61ec9405e672b6433f710ea64a90135a8dd445/mcp-1.13.1-py3-none-any.whl", hash = "sha256:c314e7c8bd477a23ba3ef472ee5a32880316c42d03e06dcfa31a1cc7a73b65df", size = 161494, upload-time = "2025-08-22T09:22:14.705Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mistralai" +version = "1.9.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "eval-type-backport" }, + { name = "httpx" }, + { name = "invoke" }, + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "pyyaml" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dc/6f/12296d29c480a4101e2bc092347895ce1a8047b6bbc52f97f124177df0b4/mistralai-1.9.8.tar.gz", hash = "sha256:74eac8b3aee410dffbd8ef0878adb7f593940fa9592d9eb4428da9b067209b22", size = 204432, upload-time = "2025-08-25T16:30:31.354Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/b3/3c1d449eea89153a77e7093e90e0282d1a718865ae6787c379256b1db288/mistralai-1.9.8-py3-none-any.whl", hash = "sha256:f4874d62932245c438c4fce04aaf740a9d6da651dc598bf660978a21fb73f017", size = 439113, upload-time = "2025-08-25T16:30:29.855Z" }, +] + +[[package]] +name = "msal" +version = "1.31.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/f3/cdf2681e83a73c3355883c2884b6ff2f2d2aadfc399c28e9ac4edc3994fd/msal-1.31.1.tar.gz", hash = "sha256:11b5e6a3f802ffd3a72107203e20c4eac6ef53401961b880af2835b723d80578", size = 145362, upload-time = "2024-11-18T09:51:10.143Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/7c/489cd931a752d05753d730e848039f08f65f86237cf1b8724d0a1cbd700b/msal-1.31.1-py3-none-any.whl", hash = "sha256:29d9882de247e96db01386496d59f29035e5e841bcac892e6d7bf4390bf6bd17", size = 113216, upload-time = "2024-11-18T09:51:08.402Z" }, +] + +[[package]] +name = "msal-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msal" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/99/5d239b6156eddf761a636bded1118414d161bd6b7b37a9335549ed159396/msal_extensions-1.3.1.tar.gz", hash = "sha256:c5b0fd10f65ef62b5f1d62f4251d51cbcaf003fcedae8c91b040a488614be1a4", size = 23315, upload-time = "2025-03-14T23:51:03.902Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/75/bd9b7bb966668920f06b200e84454c8f3566b102183bc55c5473d96cb2b9/msal_extensions-1.3.1-py3-none-any.whl", hash = "sha256:96d3de4d034504e969ac5e85bae8106c8373b5c6568e4c8fa7af2eca9dbe6bca", size = 20583, upload-time = "2025-03-14T23:51:03.016Z" }, +] + +[[package]] +name = "multidict" +version = "6.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/69/7f/0652e6ed47ab288e3756ea9c0df8b14950781184d4bd7883f4d87dd41245/multidict-6.6.4.tar.gz", hash = "sha256:d2d4e4787672911b48350df02ed3fa3fffdc2f2e8ca06dd6afdf34189b76a9dd", size = 101843, upload-time = "2025-08-11T12:08:48.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/f6/512ffd8fd8b37fb2680e5ac35d788f1d71bbaf37789d21a820bdc441e565/multidict-6.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0ffb87be160942d56d7b87b0fdf098e81ed565add09eaa1294268c7f3caac4c8", size = 76516, upload-time = "2025-08-11T12:06:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d191de6cbab2aff5de6c5723101705fd044b3e4c7cfd587a1929b5028b9714b3", size = 45394, upload-time = "2025-08-11T12:06:54.555Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/e8c4472a93a26e4507c0b8e1f0762c0d8a32de1328ef72fd704ef9cc5447/multidict-6.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38a0956dd92d918ad5feff3db8fcb4a5eb7dba114da917e1a88475619781b57b", size = 43591, upload-time = "2025-08-11T12:06:55.672Z" }, + { url = "https://files.pythonhosted.org/packages/05/51/edf414f4df058574a7265034d04c935aa84a89e79ce90fcf4df211f47b16/multidict-6.6.4-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6865f6d3b7900ae020b495d599fcf3765653bc927951c1abb959017f81ae8287", size = 237215, upload-time = "2025-08-11T12:06:57.213Z" }, + { url = "https://files.pythonhosted.org/packages/c8/45/8b3d6dbad8cf3252553cc41abea09ad527b33ce47a5e199072620b296902/multidict-6.6.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a2088c126b6f72db6c9212ad827d0ba088c01d951cee25e758c450da732c138", size = 258299, upload-time = "2025-08-11T12:06:58.946Z" }, + { url = "https://files.pythonhosted.org/packages/3c/e8/8ca2e9a9f5a435fc6db40438a55730a4bf4956b554e487fa1b9ae920f825/multidict-6.6.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0f37bed7319b848097085d7d48116f545985db988e2256b2e6f00563a3416ee6", size = 242357, upload-time = "2025-08-11T12:07:00.301Z" }, + { url = "https://files.pythonhosted.org/packages/0f/84/80c77c99df05a75c28490b2af8f7cba2a12621186e0a8b0865d8e745c104/multidict-6.6.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:01368e3c94032ba6ca0b78e7ccb099643466cf24f8dc8eefcfdc0571d56e58f9", size = 268369, upload-time = "2025-08-11T12:07:01.638Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e9/920bfa46c27b05fb3e1ad85121fd49f441492dca2449c5bcfe42e4565d8a/multidict-6.6.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fe323540c255db0bffee79ad7f048c909f2ab0edb87a597e1c17da6a54e493c", size = 269341, upload-time = "2025-08-11T12:07:02.943Z" }, + { url = "https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8eb3025f17b0a4c3cd08cda49acf312a19ad6e8a4edd9dbd591e6506d999402", size = 256100, upload-time = "2025-08-11T12:07:04.564Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/655be13ae324212bf0bc15d665a4e34844f34c206f78801be42f7a0a8aaa/multidict-6.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bbc14f0365534d35a06970d6a83478b249752e922d662dc24d489af1aa0d1be7", size = 253584, upload-time = "2025-08-11T12:07:05.914Z" }, + { url = "https://files.pythonhosted.org/packages/5c/74/ab2039ecc05264b5cec73eb018ce417af3ebb384ae9c0e9ed42cb33f8151/multidict-6.6.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:75aa52fba2d96bf972e85451b99d8e19cc37ce26fd016f6d4aa60da9ab2b005f", size = 251018, upload-time = "2025-08-11T12:07:08.301Z" }, + { url = "https://files.pythonhosted.org/packages/af/0a/ccbb244ac848e56c6427f2392741c06302bbfba49c0042f1eb3c5b606497/multidict-6.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fefd4a815e362d4f011919d97d7b4a1e566f1dde83dc4ad8cfb5b41de1df68d", size = 251477, upload-time = "2025-08-11T12:07:10.248Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b0/0ed49bba775b135937f52fe13922bc64a7eaf0a3ead84a36e8e4e446e096/multidict-6.6.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:db9801fe021f59a5b375ab778973127ca0ac52429a26e2fd86aa9508f4d26eb7", size = 263575, upload-time = "2025-08-11T12:07:11.928Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/7fb85a85e14de2e44dfb6a24f03c41e2af8697a6df83daddb0e9b7569f73/multidict-6.6.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a650629970fa21ac1fb06ba25dabfc5b8a2054fcbf6ae97c758aa956b8dba802", size = 259649, upload-time = "2025-08-11T12:07:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/03/9e/b3a459bcf9b6e74fa461a5222a10ff9b544cb1cd52fd482fb1b75ecda2a2/multidict-6.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:452ff5da78d4720d7516a3a2abd804957532dd69296cb77319c193e3ffb87e24", size = 251505, upload-time = "2025-08-11T12:07:14.57Z" }, + { url = "https://files.pythonhosted.org/packages/86/a2/8022f78f041dfe6d71e364001a5cf987c30edfc83c8a5fb7a3f0974cff39/multidict-6.6.4-cp312-cp312-win32.whl", hash = "sha256:8c2fcb12136530ed19572bbba61b407f655e3953ba669b96a35036a11a485793", size = 41888, upload-time = "2025-08-11T12:07:15.904Z" }, + { url = "https://files.pythonhosted.org/packages/c7/eb/d88b1780d43a56db2cba24289fa744a9d216c1a8546a0dc3956563fd53ea/multidict-6.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:047d9425860a8c9544fed1b9584f0c8bcd31bcde9568b047c5e567a1025ecd6e", size = 46072, upload-time = "2025-08-11T12:07:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/9f/16/b929320bf5750e2d9d4931835a4c638a19d2494a5b519caaaa7492ebe105/multidict-6.6.4-cp312-cp312-win_arm64.whl", hash = "sha256:14754eb72feaa1e8ae528468f24250dd997b8e2188c3d2f593f9eba259e4b364", size = 43222, upload-time = "2025-08-11T12:07:18.328Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5d/e1db626f64f60008320aab00fbe4f23fc3300d75892a3381275b3d284580/multidict-6.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f46a6e8597f9bd71b31cc708195d42b634c8527fecbcf93febf1052cacc1f16e", size = 75848, upload-time = "2025-08-11T12:07:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:22e38b2bc176c5eb9c0a0e379f9d188ae4cd8b28c0f53b52bce7ab0a9e534657", size = 45060, upload-time = "2025-08-11T12:07:21.163Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c6/f5e97e5d99a729bc2aa58eb3ebfa9f1e56a9b517cc38c60537c81834a73f/multidict-6.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5df8afd26f162da59e218ac0eefaa01b01b2e6cd606cffa46608f699539246da", size = 43269, upload-time = "2025-08-11T12:07:22.392Z" }, + { url = "https://files.pythonhosted.org/packages/dc/31/d54eb0c62516776f36fe67f84a732f97e0b0e12f98d5685bebcc6d396910/multidict-6.6.4-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:49517449b58d043023720aa58e62b2f74ce9b28f740a0b5d33971149553d72aa", size = 237158, upload-time = "2025-08-11T12:07:23.636Z" }, + { url = "https://files.pythonhosted.org/packages/c4/1c/8a10c1c25b23156e63b12165a929d8eb49a6ed769fdbefb06e6f07c1e50d/multidict-6.6.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9408439537c5afdca05edd128a63f56a62680f4b3c234301055d7a2000220f", size = 257076, upload-time = "2025-08-11T12:07:25.049Z" }, + { url = "https://files.pythonhosted.org/packages/ad/86/90e20b5771d6805a119e483fd3d1e8393e745a11511aebca41f0da38c3e2/multidict-6.6.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:87a32d20759dc52a9e850fe1061b6e41ab28e2998d44168a8a341b99ded1dba0", size = 240694, upload-time = "2025-08-11T12:07:26.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/49/484d3e6b535bc0555b52a0a26ba86e4d8d03fd5587d4936dc59ba7583221/multidict-6.6.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52e3c8d43cdfff587ceedce9deb25e6ae77daba560b626e97a56ddcad3756879", size = 266350, upload-time = "2025-08-11T12:07:27.94Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b4/aa4c5c379b11895083d50021e229e90c408d7d875471cb3abf721e4670d6/multidict-6.6.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ad8850921d3a8d8ff6fbef790e773cecfc260bbfa0566998980d3fa8f520bc4a", size = 267250, upload-time = "2025-08-11T12:07:29.303Z" }, + { url = "https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:497a2954adc25c08daff36f795077f63ad33e13f19bfff7736e72c785391534f", size = 254900, upload-time = "2025-08-11T12:07:30.764Z" }, + { url = "https://files.pythonhosted.org/packages/17/38/58b27fed927c07035abc02befacab42491e7388ca105e087e6e0215ead64/multidict-6.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:024ce601f92d780ca1617ad4be5ac15b501cc2414970ffa2bb2bbc2bd5a68fa5", size = 252355, upload-time = "2025-08-11T12:07:32.205Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a1/dad75d23a90c29c02b5d6f3d7c10ab36c3197613be5d07ec49c7791e186c/multidict-6.6.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a693fc5ed9bdd1c9e898013e0da4dcc640de7963a371c0bd458e50e046bf6438", size = 250061, upload-time = "2025-08-11T12:07:33.623Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1a/ac2216b61c7f116edab6dc3378cca6c70dc019c9a457ff0d754067c58b20/multidict-6.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:190766dac95aab54cae5b152a56520fd99298f32a1266d66d27fdd1b5ac00f4e", size = 249675, upload-time = "2025-08-11T12:07:34.958Z" }, + { url = "https://files.pythonhosted.org/packages/d4/79/1916af833b800d13883e452e8e0977c065c4ee3ab7a26941fbfdebc11895/multidict-6.6.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:34d8f2a5ffdceab9dcd97c7a016deb2308531d5f0fced2bb0c9e1df45b3363d7", size = 261247, upload-time = "2025-08-11T12:07:36.588Z" }, + { url = "https://files.pythonhosted.org/packages/c5/65/d1f84fe08ac44a5fc7391cbc20a7cedc433ea616b266284413fd86062f8c/multidict-6.6.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:59e8d40ab1f5a8597abcef00d04845155a5693b5da00d2c93dbe88f2050f2812", size = 257960, upload-time = "2025-08-11T12:07:39.735Z" }, + { url = "https://files.pythonhosted.org/packages/13/b5/29ec78057d377b195ac2c5248c773703a6b602e132a763e20ec0457e7440/multidict-6.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:467fe64138cfac771f0e949b938c2e1ada2b5af22f39692aa9258715e9ea613a", size = 250078, upload-time = "2025-08-11T12:07:41.525Z" }, + { url = "https://files.pythonhosted.org/packages/c4/0e/7e79d38f70a872cae32e29b0d77024bef7834b0afb406ddae6558d9e2414/multidict-6.6.4-cp313-cp313-win32.whl", hash = "sha256:14616a30fe6d0a48d0a48d1a633ab3b8bec4cf293aac65f32ed116f620adfd69", size = 41708, upload-time = "2025-08-11T12:07:43.405Z" }, + { url = "https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf", size = 45912, upload-time = "2025-08-11T12:07:45.082Z" }, + { url = "https://files.pythonhosted.org/packages/c7/87/3bac136181e271e29170d8d71929cdeddeb77f3e8b6a0c08da3a8e9da114/multidict-6.6.4-cp313-cp313-win_arm64.whl", hash = "sha256:f6eb37d511bfae9e13e82cb4d1af36b91150466f24d9b2b8a9785816deb16605", size = 43076, upload-time = "2025-08-11T12:07:46.746Z" }, + { url = "https://files.pythonhosted.org/packages/64/94/0a8e63e36c049b571c9ae41ee301ada29c3fee9643d9c2548d7d558a1d99/multidict-6.6.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6c84378acd4f37d1b507dfa0d459b449e2321b3ba5f2338f9b085cf7a7ba95eb", size = 82812, upload-time = "2025-08-11T12:07:48.402Z" }, + { url = "https://files.pythonhosted.org/packages/25/1a/be8e369dfcd260d2070a67e65dd3990dd635cbd735b98da31e00ea84cd4e/multidict-6.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0e0558693063c75f3d952abf645c78f3c5dfdd825a41d8c4d8156fc0b0da6e7e", size = 48313, upload-time = "2025-08-11T12:07:49.679Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/dd4ade298674b2f9a7b06a32c94ffbc0497354df8285f27317c66433ce3b/multidict-6.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3f8e2384cb83ebd23fd07e9eada8ba64afc4c759cd94817433ab8c81ee4b403f", size = 46777, upload-time = "2025-08-11T12:07:51.318Z" }, + { url = "https://files.pythonhosted.org/packages/89/db/98aa28bc7e071bfba611ac2ae803c24e96dd3a452b4118c587d3d872c64c/multidict-6.6.4-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f996b87b420995a9174b2a7c1a8daf7db4750be6848b03eb5e639674f7963773", size = 229321, upload-time = "2025-08-11T12:07:52.965Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bc/01ddda2a73dd9d167bd85d0e8ef4293836a8f82b786c63fb1a429bc3e678/multidict-6.6.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc356250cffd6e78416cf5b40dc6a74f1edf3be8e834cf8862d9ed5265cf9b0e", size = 249954, upload-time = "2025-08-11T12:07:54.423Z" }, + { url = "https://files.pythonhosted.org/packages/06/78/6b7c0f020f9aa0acf66d0ab4eb9f08375bac9a50ff5e3edb1c4ccd59eafc/multidict-6.6.4-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:dadf95aa862714ea468a49ad1e09fe00fcc9ec67d122f6596a8d40caf6cec7d0", size = 228612, upload-time = "2025-08-11T12:07:55.914Z" }, + { url = "https://files.pythonhosted.org/packages/00/44/3faa416f89b2d5d76e9d447296a81521e1c832ad6e40b92f990697b43192/multidict-6.6.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dd57515bebffd8ebd714d101d4c434063322e4fe24042e90ced41f18b6d3395", size = 257528, upload-time = "2025-08-11T12:07:57.371Z" }, + { url = "https://files.pythonhosted.org/packages/05/5f/77c03b89af0fcb16f018f668207768191fb9dcfb5e3361a5e706a11db2c9/multidict-6.6.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:967af5f238ebc2eb1da4e77af5492219fbd9b4b812347da39a7b5f5c72c0fa45", size = 256329, upload-time = "2025-08-11T12:07:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e9/ed750a2a9afb4f8dc6f13dc5b67b514832101b95714f1211cd42e0aafc26/multidict-6.6.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a4c6875c37aae9794308ec43e3530e4aa0d36579ce38d89979bbf89582002bb", size = 247928, upload-time = "2025-08-11T12:08:01.037Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b5/e0571bc13cda277db7e6e8a532791d4403dacc9850006cb66d2556e649c0/multidict-6.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7f683a551e92bdb7fac545b9c6f9fa2aebdeefa61d607510b3533286fcab67f5", size = 245228, upload-time = "2025-08-11T12:08:02.96Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a3/69a84b0eccb9824491f06368f5b86e72e4af54c3067c37c39099b6687109/multidict-6.6.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:3ba5aaf600edaf2a868a391779f7a85d93bed147854925f34edd24cc70a3e141", size = 235869, upload-time = "2025-08-11T12:08:04.746Z" }, + { url = "https://files.pythonhosted.org/packages/a9/9d/28802e8f9121a6a0804fa009debf4e753d0a59969ea9f70be5f5fdfcb18f/multidict-6.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:580b643b7fd2c295d83cad90d78419081f53fd532d1f1eb67ceb7060f61cff0d", size = 243446, upload-time = "2025-08-11T12:08:06.332Z" }, + { url = "https://files.pythonhosted.org/packages/38/ea/6c98add069b4878c1d66428a5f5149ddb6d32b1f9836a826ac764b9940be/multidict-6.6.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:37b7187197da6af3ee0b044dbc9625afd0c885f2800815b228a0e70f9a7f473d", size = 252299, upload-time = "2025-08-11T12:08:07.931Z" }, + { url = "https://files.pythonhosted.org/packages/3a/09/8fe02d204473e14c0af3affd50af9078839dfca1742f025cca765435d6b4/multidict-6.6.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e1b93790ed0bc26feb72e2f08299691ceb6da5e9e14a0d13cc74f1869af327a0", size = 246926, upload-time = "2025-08-11T12:08:09.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/3d/7b1e10d774a6df5175ecd3c92bff069e77bed9ec2a927fdd4ff5fe182f67/multidict-6.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a506a77ddee1efcca81ecbeae27ade3e09cdf21a8ae854d766c2bb4f14053f92", size = 243383, upload-time = "2025-08-11T12:08:10.981Z" }, + { url = "https://files.pythonhosted.org/packages/50/b0/a6fae46071b645ae98786ab738447de1ef53742eaad949f27e960864bb49/multidict-6.6.4-cp313-cp313t-win32.whl", hash = "sha256:f93b2b2279883d1d0a9e1bd01f312d6fc315c5e4c1f09e112e4736e2f650bc4e", size = 47775, upload-time = "2025-08-11T12:08:12.439Z" }, + { url = "https://files.pythonhosted.org/packages/b2/0a/2436550b1520091af0600dff547913cb2d66fbac27a8c33bc1b1bccd8d98/multidict-6.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:6d46a180acdf6e87cc41dc15d8f5c2986e1e8739dc25dbb7dac826731ef381a4", size = 53100, upload-time = "2025-08-11T12:08:13.823Z" }, + { url = "https://files.pythonhosted.org/packages/97/ea/43ac51faff934086db9c072a94d327d71b7d8b40cd5dcb47311330929ef0/multidict-6.6.4-cp313-cp313t-win_arm64.whl", hash = "sha256:756989334015e3335d087a27331659820d53ba432befdef6a718398b0a8493ad", size = 45501, upload-time = "2025-08-11T12:08:15.173Z" }, + { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, +] + +[[package]] +name = "nexus-rpc" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/66/540687556bd28cf1ec370cc6881456203dfddb9dab047b8979c6865b5984/nexus_rpc-1.1.0.tar.gz", hash = "sha256:d65ad6a2f54f14e53ebe39ee30555eaeb894102437125733fb13034a04a44553", size = 77383, upload-time = "2025-07-07T19:03:58.368Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, +] + +[[package]] +name = "openai" +version = "1.101.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/7c/eaf06b62281f5ca4f774c4cff066e6ddfd6a027e0ac791be16acec3a95e3/openai-1.101.0.tar.gz", hash = "sha256:29f56df2236069686e64aca0e13c24a4ec310545afb25ef7da2ab1a18523f22d", size = 518415, upload-time = "2025-08-21T21:11:01.645Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/a6/0e39baa335bbd1c66c7e0a41dbbec10c5a15ab95c1344e7f7beb28eee65a/openai-1.101.0-py3-none-any.whl", hash = "sha256:6539a446cce154f8d9fb42757acdfd3ed9357ab0d34fcac11096c461da87133b", size = 810772, upload-time = "2025-08-21T21:10:59.215Z" }, +] + +[[package]] +name = "opentelemetry-api" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/d2/c782c88b8afbf961d6972428821c302bd1e9e7bc361352172f0ca31296e2/opentelemetry_api-1.36.0.tar.gz", hash = "sha256:9a72572b9c416d004d492cbc6e61962c0501eaf945ece9b5a0f56597d8348aa0", size = 64780, upload-time = "2025-07-29T15:12:06.02Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/ee/6b08dde0a022c463b88f55ae81149584b125a42183407dc1045c486cc870/opentelemetry_api-1.36.0-py3-none-any.whl", hash = "sha256:02f20bcacf666e1333b6b1f04e647dc1d5111f86b8e510238fcc56d7762cda8c", size = 65564, upload-time = "2025-07-29T15:11:47.998Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/da/7747e57eb341c59886052d733072bc878424bf20f1d8cf203d508bbece5b/opentelemetry_exporter_otlp_proto_common-1.36.0.tar.gz", hash = "sha256:6c496ccbcbe26b04653cecadd92f73659b814c6e3579af157d8716e5f9f25cbf", size = 20302, upload-time = "2025-07-29T15:12:07.71Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/ed/22290dca7db78eb32e0101738366b5bbda00d0407f00feffb9bf8c3fdf87/opentelemetry_exporter_otlp_proto_common-1.36.0-py3-none-any.whl", hash = "sha256:0fc002a6ed63eac235ada9aa7056e5492e9a71728214a61745f6ad04b923f840", size = 18349, upload-time = "2025-07-29T15:11:51.327Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "requests" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/25/85/6632e7e5700ba1ce5b8a065315f92c1e6d787ccc4fb2bdab15139eaefc82/opentelemetry_exporter_otlp_proto_http-1.36.0.tar.gz", hash = "sha256:dd3637f72f774b9fc9608ab1ac479f8b44d09b6fb5b2f3df68a24ad1da7d356e", size = 16213, upload-time = "2025-07-29T15:12:08.932Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/41/a680d38b34f8f5ddbd78ed9f0042e1cc712d58ec7531924d71cb1e6c629d/opentelemetry_exporter_otlp_proto_http-1.36.0-py3-none-any.whl", hash = "sha256:3d769f68e2267e7abe4527f70deb6f598f40be3ea34c6adc35789bea94a32902", size = 18752, upload-time = "2025-07-29T15:11:53.164Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "packaging" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/37/cf17cf28f945a3aca5a038cfbb45ee01317d4f7f3a0e5209920883fe9b08/opentelemetry_instrumentation-0.57b0.tar.gz", hash = "sha256:f2a30135ba77cdea2b0e1df272f4163c154e978f57214795d72f40befd4fcf05", size = 30807, upload-time = "2025-07-29T15:42:44.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/6f/f20cd1542959f43fb26a5bf9bb18cd81a1ea0700e8870c8f369bd07f5c65/opentelemetry_instrumentation-0.57b0-py3-none-any.whl", hash = "sha256:9109280f44882e07cec2850db28210b90600ae9110b42824d196de357cbddf7e", size = 32460, upload-time = "2025-07-29T15:41:40.883Z" }, +] + +[[package]] +name = "opentelemetry-instrumentation-httpx" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-instrumentation" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "opentelemetry-util-http" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/28/65fea8b8e7f19502a8af1229c62384f9211c1480f5dee1776841810d6551/opentelemetry_instrumentation_httpx-0.57b0.tar.gz", hash = "sha256:ea5669cdb17185f8d247c2dbf756ae5b95b53110ca4d58424f2be5cc7223dbdd", size = 19511, upload-time = "2025-07-29T15:43:00.575Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/e59b319a5c6a41c6b4230f5e25651edbeb3a8d248afa1b411fd07cc3f9bf/opentelemetry_instrumentation_httpx-0.57b0-py3-none-any.whl", hash = "sha256:729fef97624016d3e5b03b71f51c9a1a2f7480b023373186d643fbed7496712a", size = 15111, upload-time = "2025-07-29T15:42:06.501Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fd/02/f6556142301d136e3b7e95ab8ea6a5d9dc28d879a99f3dd673b5f97dca06/opentelemetry_proto-1.36.0.tar.gz", hash = "sha256:0f10b3c72f74c91e0764a5ec88fd8f1c368ea5d9c64639fb455e2854ef87dd2f", size = 46152, upload-time = "2025-07-29T15:12:15.717Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/57/3361e06136225be8180e879199caea520f38026f8071366241ac458beb8d/opentelemetry_proto-1.36.0-py3-none-any.whl", hash = "sha256:151b3bf73a09f94afc658497cf77d45a565606f62ce0c17acb08cd9937ca206e", size = 72537, upload-time = "2025-07-29T15:12:02.243Z" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.36.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/85/8567a966b85a2d3f971c4d42f781c305b2b91c043724fa08fd37d158e9dc/opentelemetry_sdk-1.36.0.tar.gz", hash = "sha256:19c8c81599f51b71670661ff7495c905d8fdf6976e41622d5245b791b06fa581", size = 162557, upload-time = "2025-07-29T15:12:16.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/59/7bed362ad1137ba5886dac8439e84cd2df6d087be7c09574ece47ae9b22c/opentelemetry_sdk-1.36.0-py3-none-any.whl", hash = "sha256:19fe048b42e98c5c1ffe85b569b7073576ad4ce0bcb6e9b4c6a39e890a6c45fb", size = 119995, upload-time = "2025-07-29T15:12:03.181Z" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/31/67dfa252ee88476a29200b0255bda8dfc2cf07b56ad66dc9a6221f7dc787/opentelemetry_semantic_conventions-0.57b0.tar.gz", hash = "sha256:609a4a79c7891b4620d64c7aac6898f872d790d75f22019913a660756f27ff32", size = 124225, upload-time = "2025-07-29T15:12:17.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/75/7d591371c6c39c73de5ce5da5a2cc7b72d1d1cd3f8f4638f553c01c37b11/opentelemetry_semantic_conventions-0.57b0-py3-none-any.whl", hash = "sha256:757f7e76293294f124c827e514c2a3144f191ef175b069ce8d1211e1e38e9e78", size = 201627, upload-time = "2025-07-29T15:12:04.174Z" }, +] + +[[package]] +name = "opentelemetry-util-http" +version = "0.57b0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9b/1b/6229c45445e08e798fa825f5376f6d6a4211d29052a4088eed6d577fa653/opentelemetry_util_http-0.57b0.tar.gz", hash = "sha256:f7417595ead0eb42ed1863ec9b2f839fc740368cd7bbbfc1d0a47bc1ab0aba11", size = 9405, upload-time = "2025-07-29T15:43:19.916Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/a6/b98d508d189b9c208f5978d0906141747d7e6df7c7cafec03657ed1ed559/opentelemetry_util_http-0.57b0-py3-none-any.whl", hash = "sha256:e54c0df5543951e471c3d694f85474977cd5765a3b7654398c83bab3d2ffb8e9", size = 7643, upload-time = "2025-07-29T15:42:41.744Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, +] + +[[package]] +name = "propcache" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/16/43264e4a779dd8588c21a70f0709665ee8f611211bdd2c87d952cfa7c776/propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168", size = 44139, upload-time = "2025-06-09T22:56:06.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/42/9ca01b0a6f48e81615dca4765a8f1dd2c057e0540f6116a27dc5ee01dfb6/propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10", size = 73674, upload-time = "2025-06-09T22:54:30.551Z" }, + { url = "https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154", size = 43570, upload-time = "2025-06-09T22:54:32.296Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c8/0393a0a3a2b8760eb3bde3c147f62b20044f0ddac81e9d6ed7318ec0d852/propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615", size = 43094, upload-time = "2025-06-09T22:54:33.929Z" }, + { url = "https://files.pythonhosted.org/packages/37/2c/489afe311a690399d04a3e03b069225670c1d489eb7b044a566511c1c498/propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db", size = 226958, upload-time = "2025-06-09T22:54:35.186Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ca/63b520d2f3d418c968bf596839ae26cf7f87bead026b6192d4da6a08c467/propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1", size = 234894, upload-time = "2025-06-09T22:54:36.708Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/1d0ed6fff455a028d678df30cc28dcee7af77fa2b0e6962ce1df95c9a2a9/propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c", size = 233672, upload-time = "2025-06-09T22:54:38.062Z" }, + { url = "https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67", size = 224395, upload-time = "2025-06-09T22:54:39.634Z" }, + { url = "https://files.pythonhosted.org/packages/ee/1a/89a40e0846f5de05fdc6779883bf46ba980e6df4d2ff8fb02643de126592/propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b", size = 212510, upload-time = "2025-06-09T22:54:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/5e/33/ca98368586c9566a6b8d5ef66e30484f8da84c0aac3f2d9aec6d31a11bd5/propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8", size = 222949, upload-time = "2025-06-09T22:54:43.038Z" }, + { url = "https://files.pythonhosted.org/packages/ba/11/ace870d0aafe443b33b2f0b7efdb872b7c3abd505bfb4890716ad7865e9d/propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251", size = 217258, upload-time = "2025-06-09T22:54:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/86fd6f7adffcfc74b42c10a6b7db721d1d9ca1055c45d39a1a8f2a740a21/propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474", size = 213036, upload-time = "2025-06-09T22:54:46.243Z" }, + { url = "https://files.pythonhosted.org/packages/07/94/2d7d1e328f45ff34a0a284cf5a2847013701e24c2a53117e7c280a4316b3/propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535", size = 227684, upload-time = "2025-06-09T22:54:47.63Z" }, + { url = "https://files.pythonhosted.org/packages/b7/05/37ae63a0087677e90b1d14710e532ff104d44bc1efa3b3970fff99b891dc/propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06", size = 234562, upload-time = "2025-06-09T22:54:48.982Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7c/3f539fcae630408d0bd8bf3208b9a647ccad10976eda62402a80adf8fc34/propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1", size = 222142, upload-time = "2025-06-09T22:54:50.424Z" }, + { url = "https://files.pythonhosted.org/packages/7c/d2/34b9eac8c35f79f8a962546b3e97e9d4b990c420ee66ac8255d5d9611648/propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1", size = 37711, upload-time = "2025-06-09T22:54:52.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/61/d582be5d226cf79071681d1b46b848d6cb03d7b70af7063e33a2787eaa03/propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c", size = 41479, upload-time = "2025-06-09T22:54:53.234Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d1/8c747fafa558c603c4ca19d8e20b288aa0c7cda74e9402f50f31eb65267e/propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945", size = 71286, upload-time = "2025-06-09T22:54:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252", size = 42425, upload-time = "2025-06-09T22:54:55.642Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/ef98f91bbb42b79e9bb82bdd348b255eb9d65f14dbbe3b1594644c4073f7/propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f", size = 41846, upload-time = "2025-06-09T22:54:57.246Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ad/3f0f9a705fb630d175146cd7b1d2bf5555c9beaed54e94132b21aac098a6/propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33", size = 208871, upload-time = "2025-06-09T22:54:58.975Z" }, + { url = "https://files.pythonhosted.org/packages/3a/38/2085cda93d2c8b6ec3e92af2c89489a36a5886b712a34ab25de9fbca7992/propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e", size = 215720, upload-time = "2025-06-09T22:55:00.471Z" }, + { url = "https://files.pythonhosted.org/packages/61/c1/d72ea2dc83ac7f2c8e182786ab0fc2c7bd123a1ff9b7975bee671866fe5f/propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1", size = 215203, upload-time = "2025-06-09T22:55:01.834Z" }, + { url = "https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3", size = 206365, upload-time = "2025-06-09T22:55:03.199Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/88549128bb89e66d2aff242488f62869014ae092db63ccea53c1cc75a81d/propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1", size = 196016, upload-time = "2025-06-09T22:55:04.518Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3f/3bdd14e737d145114a5eb83cb172903afba7242f67c5877f9909a20d948d/propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6", size = 205596, upload-time = "2025-06-09T22:55:05.942Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ca/2f4aa819c357d3107c3763d7ef42c03980f9ed5c48c82e01e25945d437c1/propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387", size = 200977, upload-time = "2025-06-09T22:55:07.792Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4a/e65276c7477533c59085251ae88505caf6831c0e85ff8b2e31ebcbb949b1/propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4", size = 197220, upload-time = "2025-06-09T22:55:09.173Z" }, + { url = "https://files.pythonhosted.org/packages/7c/54/fc7152e517cf5578278b242396ce4d4b36795423988ef39bb8cd5bf274c8/propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88", size = 210642, upload-time = "2025-06-09T22:55:10.62Z" }, + { url = "https://files.pythonhosted.org/packages/b9/80/abeb4a896d2767bf5f1ea7b92eb7be6a5330645bd7fb844049c0e4045d9d/propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206", size = 212789, upload-time = "2025-06-09T22:55:12.029Z" }, + { url = "https://files.pythonhosted.org/packages/b3/db/ea12a49aa7b2b6d68a5da8293dcf50068d48d088100ac016ad92a6a780e6/propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43", size = 205880, upload-time = "2025-06-09T22:55:13.45Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e5/9076a0bbbfb65d1198007059c65639dfd56266cf8e477a9707e4b1999ff4/propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02", size = 37220, upload-time = "2025-06-09T22:55:15.284Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05", size = 40678, upload-time = "2025-06-09T22:55:16.445Z" }, + { url = "https://files.pythonhosted.org/packages/a4/3a/6ece377b55544941a08d03581c7bc400a3c8cd3c2865900a68d5de79e21f/propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b", size = 76560, upload-time = "2025-06-09T22:55:17.598Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/64a2bb16418740fa634b0e9c3d29edff1db07f56d3546ca2d86ddf0305e1/propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0", size = 44676, upload-time = "2025-06-09T22:55:18.922Z" }, + { url = "https://files.pythonhosted.org/packages/36/7b/f025e06ea51cb72c52fb87e9b395cced02786610b60a3ed51da8af017170/propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e", size = 44701, upload-time = "2025-06-09T22:55:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/a4/00/faa1b1b7c3b74fc277f8642f32a4c72ba1d7b2de36d7cdfb676db7f4303e/propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28", size = 276934, upload-time = "2025-06-09T22:55:21.5Z" }, + { url = "https://files.pythonhosted.org/packages/74/ab/935beb6f1756e0476a4d5938ff44bf0d13a055fed880caf93859b4f1baf4/propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a", size = 278316, upload-time = "2025-06-09T22:55:22.918Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9d/994a5c1ce4389610838d1caec74bdf0e98b306c70314d46dbe4fcf21a3e2/propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c", size = 282619, upload-time = "2025-06-09T22:55:24.651Z" }, + { url = "https://files.pythonhosted.org/packages/2b/00/a10afce3d1ed0287cef2e09506d3be9822513f2c1e96457ee369adb9a6cd/propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725", size = 265896, upload-time = "2025-06-09T22:55:26.049Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a8/2aa6716ffa566ca57c749edb909ad27884680887d68517e4be41b02299f3/propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892", size = 252111, upload-time = "2025-06-09T22:55:27.381Z" }, + { url = "https://files.pythonhosted.org/packages/36/4f/345ca9183b85ac29c8694b0941f7484bf419c7f0fea2d1e386b4f7893eed/propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44", size = 268334, upload-time = "2025-06-09T22:55:28.747Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ca/fcd54f78b59e3f97b3b9715501e3147f5340167733d27db423aa321e7148/propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe", size = 255026, upload-time = "2025-06-09T22:55:30.184Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8e6a6bbbd78ac89c30c225210a5c687790e532ba4088afb8c0445b77ef37/propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81", size = 250724, upload-time = "2025-06-09T22:55:31.646Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b0/0dd03616142baba28e8b2d14ce5df6631b4673850a3d4f9c0f9dd714a404/propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba", size = 268868, upload-time = "2025-06-09T22:55:33.209Z" }, + { url = "https://files.pythonhosted.org/packages/c5/98/2c12407a7e4fbacd94ddd32f3b1e3d5231e77c30ef7162b12a60e2dd5ce3/propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770", size = 271322, upload-time = "2025-06-09T22:55:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/35/91/9cb56efbb428b006bb85db28591e40b7736847b8331d43fe335acf95f6c8/propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330", size = 265778, upload-time = "2025-06-09T22:55:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4c/b0fe775a2bdd01e176b14b574be679d84fc83958335790f7c9a686c1f468/propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394", size = 41175, upload-time = "2025-06-09T22:55:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ff/47f08595e3d9b5e149c150f88d9714574f1a7cbd89fe2817158a952674bf/propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198", size = 44857, upload-time = "2025-06-09T22:55:39.687Z" }, + { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, +] + +[[package]] +name = "protobuf" +version = "5.29.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/29/d09e70352e4e88c9c7a198d5645d7277811448d76c23b00345670f7c8a38/protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84", size = 425226, upload-time = "2025-05-28T23:51:59.82Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/11/6e40e9fc5bba02988a214c07cf324595789ca7820160bfd1f8be96e48539/protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079", size = 422963, upload-time = "2025-05-28T23:51:41.204Z" }, + { url = "https://files.pythonhosted.org/packages/81/7f/73cefb093e1a2a7c3ffd839e6f9fcafb7a427d300c7f8aef9c64405d8ac6/protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc", size = 434818, upload-time = "2025-05-28T23:51:44.297Z" }, + { url = "https://files.pythonhosted.org/packages/dd/73/10e1661c21f139f2c6ad9b23040ff36fee624310dc28fba20d33fdae124c/protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671", size = 418091, upload-time = "2025-05-28T23:51:45.907Z" }, + { url = "https://files.pythonhosted.org/packages/6c/04/98f6f8cf5b07ab1294c13f34b4e69b3722bb609c5b701d6c169828f9f8aa/protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015", size = 319824, upload-time = "2025-05-28T23:51:47.545Z" }, + { url = "https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61", size = 319942, upload-time = "2025-05-28T23:51:49.11Z" }, + { url = "https://files.pythonhosted.org/packages/7e/cc/7e77861000a0691aeea8f4566e5d3aa716f2b1dece4a24439437e41d3d25/protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5", size = 172823, upload-time = "2025-05-28T23:51:58.157Z" }, +] + +[[package]] +name = "pyasn1" +version = "0.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, +] + +[[package]] +name = "pydantic" +version = "2.11.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, +] + +[[package]] +name = "pydantic-ai" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic-ai-slim", extra = ["ag-ui", "anthropic", "bedrock", "cli", "cohere", "evals", "google", "groq", "huggingface", "logfire", "mcp", "mistral", "openai", "retries", "temporal", "vertexai"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/41/b3cab0ae7bd94ade25dc41343fee8f46e35c2ad43b79a443456a5c59d9cf/pydantic_ai-1.0.2.tar.gz", hash = "sha256:0ed625db02bece2ce6e52c6326fc5f9c78482693ff89ce93477aec17687b20a5", size = 43802817, upload-time = "2025-09-09T00:38:33.049Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/fd/61b361553c77f36848f470908ac55c76624b17a1831b43da074f449650b8/pydantic_ai-1.0.2-py3-none-any.whl", hash = "sha256:616c224948097c2bb1607cd4aa87e971f94d3eb891156c9d77e94c18e346c839", size = 11670, upload-time = "2025-09-09T00:38:21.777Z" }, +] + +[[package]] +name = "pydantic-ai-slim" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "genai-prices" }, + { name = "griffe" }, + { name = "httpx" }, + { name = "opentelemetry-api" }, + { name = "pydantic" }, + { name = "pydantic-graph" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/fd/962a6d79b135cd2ed30d122431b73cb725a8f9206706dd95a35a0e442439/pydantic_ai_slim-1.0.2.tar.gz", hash = "sha256:a41642f9c248ab1e12911f54c5c5adff4b2667ef48c5578eeea718febb108395", size = 235860, upload-time = "2025-09-09T00:38:37.665Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/74/b68d3c61219d8b9ea67baefa0efcf7e20c641c4efef842100c0715c81b85/pydantic_ai_slim-1.0.2-py3-none-any.whl", hash = "sha256:d72922f7c0684c556c1182eee5281510a357c2f18bb3e54a9f117f548a74c236", size = 318441, upload-time = "2025-09-09T00:38:25.828Z" }, +] + +[package.optional-dependencies] +ag-ui = [ + { name = "ag-ui-protocol" }, + { name = "starlette" }, +] +anthropic = [ + { name = "anthropic" }, +] +bedrock = [ + { name = "boto3" }, +] +cli = [ + { name = "argcomplete" }, + { name = "prompt-toolkit" }, + { name = "pyperclip" }, + { name = "rich" }, +] +cohere = [ + { name = "cohere", marker = "sys_platform != 'emscripten'" }, +] +evals = [ + { name = "pydantic-evals" }, +] +google = [ + { name = "google-genai" }, +] +groq = [ + { name = "groq" }, +] +huggingface = [ + { name = "huggingface-hub", extra = ["inference"] }, +] +logfire = [ + { name = "logfire", extra = ["httpx"] }, +] +mcp = [ + { name = "mcp" }, +] +mistral = [ + { name = "mistralai" }, +] +openai = [ + { name = "openai" }, +] +retries = [ + { name = "tenacity" }, +] +temporal = [ + { name = "temporalio" }, +] +vertexai = [ + { name = "google-auth" }, + { name = "requests" }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, +] + +[[package]] +name = "pydantic-evals" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "pydantic-ai-slim" }, + { name = "pyyaml" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/62/1cd84d70362f2afaaacd1ae102ba46012156ec41c76762d7242bb9705b89/pydantic_evals-1.0.2.tar.gz", hash = "sha256:071bc4b80e1ced065ebcea53e03f06eca868266658a56dfb98ca78976f9022c8", size = 45489, upload-time = "2025-09-09T00:38:38.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/ff/63d8a76e50455b3d755cc940a5cc3f00d26c2a3636930f26f2b0e8f89fc4/pydantic_evals-1.0.2-py3-none-any.whl", hash = "sha256:48ea9510bc66ca2052298cd5a587306fa450f615d3e6542cbb021168b4cfc375", size = 54598, upload-time = "2025-09-09T00:38:27.82Z" }, +] + +[[package]] +name = "pydantic-graph" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "logfire-api" }, + { name = "pydantic" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/6d/c5a22894828a93e99a2d36d12749619afc7d561aaa926c7d2098e62ad8b5/pydantic_graph-1.0.2.tar.gz", hash = "sha256:249e0b834a37ae31846c93491c949a981179e6206f5b487e7421eb6380abb682", size = 21892, upload-time = "2025-09-09T00:38:40.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ac/9e/3f34115d2795d260e2a19a2cdce399ffa045aeed5532e46ed62155dec529/pydantic_graph-1.0.2-py3-none-any.whl", hash = "sha256:383811cf6802697d31eea3309fdf2738aef333c68e780e1b3f9dbd60c4e2ad97", size = 27536, upload-time = "2025-09-09T00:38:29.39Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583, upload-time = "2025-06-24T13:26:46.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/68/ce067f09fca4abeca8771fe667d89cc347d1e99da3e093112ac329c6020e/pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c", size = 78825, upload-time = "2024-08-01T15:01:08.445Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/84/0fdf9b18ba31d69877bd39c9cd6052b47f3761e9910c15de788e519f079f/PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", size = 22344, upload-time = "2024-08-01T15:01:06.481Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + +[[package]] +name = "pyperclip" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/23/2f0a3efc4d6a32f3b63cdff36cd398d9701d26cda58e3ab97ac79fb5e60d/pyperclip-1.9.0.tar.gz", hash = "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310", size = 20961, upload-time = "2024-06-18T20:38:48.401Z" } + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + +[[package]] +name = "redis" +version = "6.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/d6/e8b92798a5bd67d659d51a18170e91c16ac3b59738d91894651ee255ed49/redis-6.4.0.tar.gz", hash = "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010", size = 4647399, upload-time = "2025-08-07T08:10:11.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/02/89e2ed7e85db6c93dfa9e8f691c5087df4e3551ab39081a4d7c6d1f90e05/redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f", size = 279847, upload-time = "2025-08-07T08:10:09.84Z" }, +] + +[[package]] +name = "redis-entraid" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-identity" }, + { name = "msal" }, + { name = "pyjwt" }, + { name = "redis" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/7b/f56aebb76ce71368e34e27c096537f2ee0249268f11eefee03dc6268c552/redis_entraid-1.0.0.tar.gz", hash = "sha256:585188b49597a70ad149ef012f20e478baf0d722c1a148318146db635be5a71e", size = 9550, upload-time = "2025-05-27T11:46:32.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/3c/187d524f735e531cf7c2e6adc660ac48860b4784a54663bf5dbc972b2f38/redis_entraid-1.0.0-py3-none-any.whl", hash = "sha256:4c9ec857e26e9ed2b3810ddb28b2f33a28035712ccba0dc8b55c70a3bf8a9908", size = 7864, upload-time = "2025-05-27T11:46:31.732Z" }, +] + +[[package]] +name = "referencing" +version = "0.36.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/db/98b5c277be99dd18bfd91dd04e1b759cad18d1a338188c936e92f921c7e2/referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", size = 74744, upload-time = "2025-01-25T08:48:16.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0", size = 26775, upload-time = "2025-01-25T08:48:14.241Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rich" +version = "14.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/d9/991a0dee12d9fc53ed027e26a26a64b151d77252ac477e22666b9688bc16/rpds_py-0.27.0.tar.gz", hash = "sha256:8b23cf252f180cda89220b378d917180f29d313cd6a07b2431c0d3b776aae86f", size = 27420, upload-time = "2025-08-07T08:26:39.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/17/e67309ca1ac993fa1888a0d9b2f5ccc1f67196ace32e76c9f8e1dbbbd50c/rpds_py-0.27.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:19c990fdf5acecbf0623e906ae2e09ce1c58947197f9bced6bbd7482662231c4", size = 362611, upload-time = "2025-08-07T08:23:44.773Z" }, + { url = "https://files.pythonhosted.org/packages/93/2e/28c2fb84aa7aa5d75933d1862d0f7de6198ea22dfd9a0cca06e8a4e7509e/rpds_py-0.27.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c27a7054b5224710fcfb1a626ec3ff4f28bcb89b899148c72873b18210e446b", size = 347680, upload-time = "2025-08-07T08:23:46.014Z" }, + { url = "https://files.pythonhosted.org/packages/44/3e/9834b4c8f4f5fe936b479e623832468aa4bd6beb8d014fecaee9eac6cdb1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09965b314091829b378b60607022048953e25f0b396c2b70e7c4c81bcecf932e", size = 384600, upload-time = "2025-08-07T08:23:48Z" }, + { url = "https://files.pythonhosted.org/packages/19/78/744123c7b38865a965cd9e6f691fde7ef989a00a256fa8bf15b75240d12f/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:14f028eb47f59e9169bfdf9f7ceafd29dd64902141840633683d0bad5b04ff34", size = 400697, upload-time = "2025-08-07T08:23:49.407Z" }, + { url = "https://files.pythonhosted.org/packages/32/97/3c3d32fe7daee0a1f1a678b6d4dfb8c4dcf88197fa2441f9da7cb54a8466/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6168af0be75bba990a39f9431cdfae5f0ad501f4af32ae62e8856307200517b8", size = 517781, upload-time = "2025-08-07T08:23:50.557Z" }, + { url = "https://files.pythonhosted.org/packages/b2/be/28f0e3e733680aa13ecec1212fc0f585928a206292f14f89c0b8a684cad1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab47fe727c13c09d0e6f508e3a49e545008e23bf762a245b020391b621f5b726", size = 406449, upload-time = "2025-08-07T08:23:51.732Z" }, + { url = "https://files.pythonhosted.org/packages/95/ae/5d15c83e337c082d0367053baeb40bfba683f42459f6ebff63a2fd7e5518/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa01b3d5e3b7d97efab65bd3d88f164e289ec323a8c033c5c38e53ee25c007e", size = 386150, upload-time = "2025-08-07T08:23:52.822Z" }, + { url = "https://files.pythonhosted.org/packages/bf/65/944e95f95d5931112829e040912b25a77b2e7ed913ea5fe5746aa5c1ce75/rpds_py-0.27.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:6c135708e987f46053e0a1246a206f53717f9fadfba27174a9769ad4befba5c3", size = 406100, upload-time = "2025-08-07T08:23:54.339Z" }, + { url = "https://files.pythonhosted.org/packages/21/a4/1664b83fae02894533cd11dc0b9f91d673797c2185b7be0f7496107ed6c5/rpds_py-0.27.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc327f4497b7087d06204235199daf208fd01c82d80465dc5efa4ec9df1c5b4e", size = 421345, upload-time = "2025-08-07T08:23:55.832Z" }, + { url = "https://files.pythonhosted.org/packages/7c/26/b7303941c2b0823bfb34c71378249f8beedce57301f400acb04bb345d025/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e57906e38583a2cba67046a09c2637e23297618dc1f3caddbc493f2be97c93f", size = 561891, upload-time = "2025-08-07T08:23:56.951Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c8/48623d64d4a5a028fa99576c768a6159db49ab907230edddc0b8468b998b/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f4f69d7a4300fbf91efb1fb4916421bd57804c01ab938ab50ac9c4aa2212f03", size = 591756, upload-time = "2025-08-07T08:23:58.146Z" }, + { url = "https://files.pythonhosted.org/packages/b3/51/18f62617e8e61cc66334c9fb44b1ad7baae3438662098efbc55fb3fda453/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b4c4fbbcff474e1e5f38be1bf04511c03d492d42eec0babda5d03af3b5589374", size = 557088, upload-time = "2025-08-07T08:23:59.6Z" }, + { url = "https://files.pythonhosted.org/packages/bd/4c/e84c3a276e2496a93d245516be6b49e20499aa8ca1c94d59fada0d79addc/rpds_py-0.27.0-cp312-cp312-win32.whl", hash = "sha256:27bac29bbbf39601b2aab474daf99dbc8e7176ca3389237a23944b17f8913d97", size = 221926, upload-time = "2025-08-07T08:24:00.695Z" }, + { url = "https://files.pythonhosted.org/packages/83/89/9d0fbcef64340db0605eb0a0044f258076f3ae0a3b108983b2c614d96212/rpds_py-0.27.0-cp312-cp312-win_amd64.whl", hash = "sha256:8a06aa1197ec0281eb1d7daf6073e199eb832fe591ffa329b88bae28f25f5fe5", size = 233235, upload-time = "2025-08-07T08:24:01.846Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b0/e177aa9f39cbab060f96de4a09df77d494f0279604dc2f509263e21b05f9/rpds_py-0.27.0-cp312-cp312-win_arm64.whl", hash = "sha256:e14aab02258cb776a108107bd15f5b5e4a1bbaa61ef33b36693dfab6f89d54f9", size = 223315, upload-time = "2025-08-07T08:24:03.337Z" }, + { url = "https://files.pythonhosted.org/packages/81/d2/dfdfd42565a923b9e5a29f93501664f5b984a802967d48d49200ad71be36/rpds_py-0.27.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:443d239d02d9ae55b74015234f2cd8eb09e59fbba30bf60baeb3123ad4c6d5ff", size = 362133, upload-time = "2025-08-07T08:24:04.508Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/0a2e2460c4b66021d349ce9f6331df1d6c75d7eea90df9785d333a49df04/rpds_py-0.27.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8a7acf04fda1f30f1007f3cc96d29d8cf0a53e626e4e1655fdf4eabc082d367", size = 347128, upload-time = "2025-08-07T08:24:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/35/8d/7d1e4390dfe09d4213b3175a3f5a817514355cb3524593380733204f20b9/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0f92b78cfc3b74a42239fdd8c1266f4715b573204c234d2f9fc3fc7a24f185", size = 384027, upload-time = "2025-08-07T08:24:06.841Z" }, + { url = "https://files.pythonhosted.org/packages/c1/65/78499d1a62172891c8cd45de737b2a4b84a414b6ad8315ab3ac4945a5b61/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ce4ed8e0c7dbc5b19352b9c2c6131dd23b95fa8698b5cdd076307a33626b72dc", size = 399973, upload-time = "2025-08-07T08:24:08.143Z" }, + { url = "https://files.pythonhosted.org/packages/10/a1/1c67c1d8cc889107b19570bb01f75cf49852068e95e6aee80d22915406fc/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fde355b02934cc6b07200cc3b27ab0c15870a757d1a72fd401aa92e2ea3c6bfe", size = 515295, upload-time = "2025-08-07T08:24:09.711Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/700ec88e748436b6c7c4a2262d66e80f8c21ab585d5e98c45e02f13f21c0/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13bbc4846ae4c993f07c93feb21a24d8ec637573d567a924b1001e81c8ae80f9", size = 406737, upload-time = "2025-08-07T08:24:11.182Z" }, + { url = "https://files.pythonhosted.org/packages/33/cc/6b0ee8f0ba3f2df2daac1beda17fde5cf10897a7d466f252bd184ef20162/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0744661afbc4099fef7f4e604e7f1ea1be1dd7284f357924af12a705cc7d5c", size = 385898, upload-time = "2025-08-07T08:24:12.798Z" }, + { url = "https://files.pythonhosted.org/packages/e8/7e/c927b37d7d33c0a0ebf249cc268dc2fcec52864c1b6309ecb960497f2285/rpds_py-0.27.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:069e0384a54f427bd65d7fda83b68a90606a3835901aaff42185fcd94f5a9295", size = 405785, upload-time = "2025-08-07T08:24:14.906Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/8ed50746d909dcf402af3fa58b83d5a590ed43e07251d6b08fad1a535ba6/rpds_py-0.27.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4bc262ace5a1a7dc3e2eac2fa97b8257ae795389f688b5adf22c5db1e2431c43", size = 419760, upload-time = "2025-08-07T08:24:16.129Z" }, + { url = "https://files.pythonhosted.org/packages/d3/60/2b2071aee781cb3bd49f94d5d35686990b925e9b9f3e3d149235a6f5d5c1/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2fe6e18e5c8581f0361b35ae575043c7029d0a92cb3429e6e596c2cdde251432", size = 561201, upload-time = "2025-08-07T08:24:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/98/1f/27b67304272521aaea02be293fecedce13fa351a4e41cdb9290576fc6d81/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d93ebdb82363d2e7bec64eecdc3632b59e84bd270d74fe5be1659f7787052f9b", size = 591021, upload-time = "2025-08-07T08:24:18.999Z" }, + { url = "https://files.pythonhosted.org/packages/db/9b/a2fadf823164dd085b1f894be6443b0762a54a7af6f36e98e8fcda69ee50/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0954e3a92e1d62e83a54ea7b3fdc9efa5d61acef8488a8a3d31fdafbfb00460d", size = 556368, upload-time = "2025-08-07T08:24:20.54Z" }, + { url = "https://files.pythonhosted.org/packages/24/f3/6d135d46a129cda2e3e6d4c5e91e2cc26ea0428c6cf152763f3f10b6dd05/rpds_py-0.27.0-cp313-cp313-win32.whl", hash = "sha256:2cff9bdd6c7b906cc562a505c04a57d92e82d37200027e8d362518df427f96cd", size = 221236, upload-time = "2025-08-07T08:24:22.144Z" }, + { url = "https://files.pythonhosted.org/packages/c5/44/65d7494f5448ecc755b545d78b188440f81da98b50ea0447ab5ebfdf9bd6/rpds_py-0.27.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc79d192fb76fc0c84f2c58672c17bbbc383fd26c3cdc29daae16ce3d927e8b2", size = 232634, upload-time = "2025-08-07T08:24:23.642Z" }, + { url = "https://files.pythonhosted.org/packages/70/d9/23852410fadab2abb611733933401de42a1964ce6600a3badae35fbd573e/rpds_py-0.27.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b3a5c8089eed498a3af23ce87a80805ff98f6ef8f7bdb70bd1b7dae5105f6ac", size = 222783, upload-time = "2025-08-07T08:24:25.098Z" }, + { url = "https://files.pythonhosted.org/packages/15/75/03447917f78512b34463f4ef11066516067099a0c466545655503bed0c77/rpds_py-0.27.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:90fb790138c1a89a2e58c9282fe1089638401f2f3b8dddd758499041bc6e0774", size = 359154, upload-time = "2025-08-07T08:24:26.249Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fc/4dac4fa756451f2122ddaf136e2c6aeb758dc6fdbe9ccc4bc95c98451d50/rpds_py-0.27.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:010c4843a3b92b54373e3d2291a7447d6c3fc29f591772cc2ea0e9f5c1da434b", size = 343909, upload-time = "2025-08-07T08:24:27.405Z" }, + { url = "https://files.pythonhosted.org/packages/7b/81/723c1ed8e6f57ed9d8c0c07578747a2d3d554aaefc1ab89f4e42cfeefa07/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9ce7a9e967afc0a2af7caa0d15a3e9c1054815f73d6a8cb9225b61921b419bd", size = 379340, upload-time = "2025-08-07T08:24:28.714Z" }, + { url = "https://files.pythonhosted.org/packages/98/16/7e3740413de71818ce1997df82ba5f94bae9fff90c0a578c0e24658e6201/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa0bf113d15e8abdfee92aa4db86761b709a09954083afcb5bf0f952d6065fdb", size = 391655, upload-time = "2025-08-07T08:24:30.223Z" }, + { url = "https://files.pythonhosted.org/packages/e0/63/2a9f510e124d80660f60ecce07953f3f2d5f0b96192c1365443859b9c87f/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb91d252b35004a84670dfeafadb042528b19842a0080d8b53e5ec1128e8f433", size = 513017, upload-time = "2025-08-07T08:24:31.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/4e/cf6ff311d09776c53ea1b4f2e6700b9d43bb4e99551006817ade4bbd6f78/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db8a6313dbac934193fc17fe7610f70cd8181c542a91382531bef5ed785e5615", size = 402058, upload-time = "2025-08-07T08:24:32.613Z" }, + { url = "https://files.pythonhosted.org/packages/88/11/5e36096d474cb10f2a2d68b22af60a3bc4164fd8db15078769a568d9d3ac/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce96ab0bdfcef1b8c371ada2100767ace6804ea35aacce0aef3aeb4f3f499ca8", size = 383474, upload-time = "2025-08-07T08:24:33.767Z" }, + { url = "https://files.pythonhosted.org/packages/db/a2/3dff02805b06058760b5eaa6d8cb8db3eb3e46c9e452453ad5fc5b5ad9fe/rpds_py-0.27.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:7451ede3560086abe1aa27dcdcf55cd15c96b56f543fb12e5826eee6f721f858", size = 400067, upload-time = "2025-08-07T08:24:35.021Z" }, + { url = "https://files.pythonhosted.org/packages/67/87/eed7369b0b265518e21ea836456a4ed4a6744c8c12422ce05bce760bb3cf/rpds_py-0.27.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:32196b5a99821476537b3f7732432d64d93a58d680a52c5e12a190ee0135d8b5", size = 412085, upload-time = "2025-08-07T08:24:36.267Z" }, + { url = "https://files.pythonhosted.org/packages/8b/48/f50b2ab2fbb422fbb389fe296e70b7a6b5ea31b263ada5c61377e710a924/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a029be818059870664157194e46ce0e995082ac49926f1423c1f058534d2aaa9", size = 555928, upload-time = "2025-08-07T08:24:37.573Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/b18eb51045d06887666c3560cd4bbb6819127b43d758f5adb82b5f56f7d1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3841f66c1ffdc6cebce8aed64e36db71466f1dc23c0d9a5592e2a782a3042c79", size = 585527, upload-time = "2025-08-07T08:24:39.391Z" }, + { url = "https://files.pythonhosted.org/packages/be/03/a3dd6470fc76499959b00ae56295b76b4bdf7c6ffc60d62006b1217567e1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:42894616da0fc0dcb2ec08a77896c3f56e9cb2f4b66acd76fc8992c3557ceb1c", size = 554211, upload-time = "2025-08-07T08:24:40.6Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d1/ee5fd1be395a07423ac4ca0bcc05280bf95db2b155d03adefeb47d5ebf7e/rpds_py-0.27.0-cp313-cp313t-win32.whl", hash = "sha256:b1fef1f13c842a39a03409e30ca0bf87b39a1e2a305a9924deadb75a43105d23", size = 216624, upload-time = "2025-08-07T08:24:42.204Z" }, + { url = "https://files.pythonhosted.org/packages/1c/94/4814c4c858833bf46706f87349c37ca45e154da7dbbec9ff09f1abeb08cc/rpds_py-0.27.0-cp313-cp313t-win_amd64.whl", hash = "sha256:183f5e221ba3e283cd36fdfbe311d95cd87699a083330b4f792543987167eff1", size = 230007, upload-time = "2025-08-07T08:24:43.329Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a5/8fffe1c7dc7c055aa02df310f9fb71cfc693a4d5ccc5de2d3456ea5fb022/rpds_py-0.27.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f3cd110e02c5bf17d8fb562f6c9df5c20e73029d587cf8602a2da6c5ef1e32cb", size = 362595, upload-time = "2025-08-07T08:24:44.478Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c7/4e4253fd2d4bb0edbc0b0b10d9f280612ca4f0f990e3c04c599000fe7d71/rpds_py-0.27.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8d0e09cf4863c74106b5265c2c310f36146e2b445ff7b3018a56799f28f39f6f", size = 347252, upload-time = "2025-08-07T08:24:45.678Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c8/3d1a954d30f0174dd6baf18b57c215da03cf7846a9d6e0143304e784cddc/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f689ab822f9b5eb6dfc69893b4b9366db1d2420f7db1f6a2adf2a9ca15ad64", size = 384886, upload-time = "2025-08-07T08:24:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/e0/52/3c5835f2df389832b28f9276dd5395b5a965cea34226e7c88c8fbec2093c/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e36c80c49853b3ffda7aa1831bf175c13356b210c73128c861f3aa93c3cc4015", size = 399716, upload-time = "2025-08-07T08:24:48.174Z" }, + { url = "https://files.pythonhosted.org/packages/40/73/176e46992461a1749686a2a441e24df51ff86b99c2d34bf39f2a5273b987/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6de6a7f622860af0146cb9ee148682ff4d0cea0b8fd3ad51ce4d40efb2f061d0", size = 517030, upload-time = "2025-08-07T08:24:49.52Z" }, + { url = "https://files.pythonhosted.org/packages/79/2a/7266c75840e8c6e70effeb0d38922a45720904f2cd695e68a0150e5407e2/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4045e2fc4b37ec4b48e8907a5819bdd3380708c139d7cc358f03a3653abedb89", size = 408448, upload-time = "2025-08-07T08:24:50.727Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5f/a7efc572b8e235093dc6cf39f4dbc8a7f08e65fdbcec7ff4daeb3585eef1/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da162b718b12c4219eeeeb68a5b7552fbc7aadedf2efee440f88b9c0e54b45d", size = 387320, upload-time = "2025-08-07T08:24:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/a2/eb/9ff6bc92efe57cf5a2cb74dee20453ba444b6fdc85275d8c99e0d27239d1/rpds_py-0.27.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:0665be515767dc727ffa5f74bd2ef60b0ff85dad6bb8f50d91eaa6b5fb226f51", size = 407414, upload-time = "2025-08-07T08:24:53.664Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bd/3b9b19b00d5c6e1bd0f418c229ab0f8d3b110ddf7ec5d9d689ef783d0268/rpds_py-0.27.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:203f581accef67300a942e49a37d74c12ceeef4514874c7cede21b012613ca2c", size = 420766, upload-time = "2025-08-07T08:24:55.917Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/521a7b1079ce16258c70805166e3ac6ec4ee2139d023fe07954dc9b2d568/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7873b65686a6471c0037139aa000d23fe94628e0daaa27b6e40607c90e3f5ec4", size = 562409, upload-time = "2025-08-07T08:24:57.17Z" }, + { url = "https://files.pythonhosted.org/packages/8b/bf/65db5bfb14ccc55e39de8419a659d05a2a9cd232f0a699a516bb0991da7b/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:249ab91ceaa6b41abc5f19513cb95b45c6f956f6b89f1fe3d99c81255a849f9e", size = 590793, upload-time = "2025-08-07T08:24:58.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/b8/82d368b378325191ba7aae8f40f009b78057b598d4394d1f2cdabaf67b3f/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d2f184336bc1d6abfaaa1262ed42739c3789b1e3a65a29916a615307d22ffd2e", size = 558178, upload-time = "2025-08-07T08:24:59.756Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ff/f270bddbfbc3812500f8131b1ebbd97afd014cd554b604a3f73f03133a36/rpds_py-0.27.0-cp314-cp314-win32.whl", hash = "sha256:d3c622c39f04d5751408f5b801ecb527e6e0a471b367f420a877f7a660d583f6", size = 222355, upload-time = "2025-08-07T08:25:01.027Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/fdab055b1460c02ed356a0e0b0a78c1dd32dc64e82a544f7b31c9ac643dc/rpds_py-0.27.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf824aceaeffff029ccfba0da637d432ca71ab21f13e7f6f5179cd88ebc77a8a", size = 234007, upload-time = "2025-08-07T08:25:02.268Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a8/694c060005421797a3be4943dab8347c76c2b429a9bef68fb2c87c9e70c7/rpds_py-0.27.0-cp314-cp314-win_arm64.whl", hash = "sha256:86aca1616922b40d8ac1b3073a1ead4255a2f13405e5700c01f7c8d29a03972d", size = 223527, upload-time = "2025-08-07T08:25:03.45Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f9/77f4c90f79d2c5ca8ce6ec6a76cb4734ee247de6b3a4f337e289e1f00372/rpds_py-0.27.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:341d8acb6724c0c17bdf714319c393bb27f6d23d39bc74f94221b3e59fc31828", size = 359469, upload-time = "2025-08-07T08:25:04.648Z" }, + { url = "https://files.pythonhosted.org/packages/c0/22/b97878d2f1284286fef4172069e84b0b42b546ea7d053e5fb7adb9ac6494/rpds_py-0.27.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6b96b0b784fe5fd03beffff2b1533dc0d85e92bab8d1b2c24ef3a5dc8fac5669", size = 343960, upload-time = "2025-08-07T08:25:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b0/dfd55b5bb480eda0578ae94ef256d3061d20b19a0f5e18c482f03e65464f/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c431bfb91478d7cbe368d0a699978050d3b112d7f1d440a41e90faa325557fd", size = 380201, upload-time = "2025-08-07T08:25:07.513Z" }, + { url = "https://files.pythonhosted.org/packages/28/22/e1fa64e50d58ad2b2053077e3ec81a979147c43428de9e6de68ddf6aff4e/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e222a44ae9f507d0f2678ee3dd0c45ec1e930f6875d99b8459631c24058aec", size = 392111, upload-time = "2025-08-07T08:25:09.149Z" }, + { url = "https://files.pythonhosted.org/packages/49/f9/43ab7a43e97aedf6cea6af70fdcbe18abbbc41d4ae6cdec1bfc23bbad403/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:184f0d7b342967f6cda94a07d0e1fae177d11d0b8f17d73e06e36ac02889f303", size = 515863, upload-time = "2025-08-07T08:25:10.431Z" }, + { url = "https://files.pythonhosted.org/packages/38/9b/9bd59dcc636cd04d86a2d20ad967770bf348f5eb5922a8f29b547c074243/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a00c91104c173c9043bc46f7b30ee5e6d2f6b1149f11f545580f5d6fdff42c0b", size = 402398, upload-time = "2025-08-07T08:25:11.819Z" }, + { url = "https://files.pythonhosted.org/packages/71/bf/f099328c6c85667aba6b66fa5c35a8882db06dcd462ea214be72813a0dd2/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a37dd208f0d658e0487522078b1ed68cd6bce20ef4b5a915d2809b9094b410", size = 384665, upload-time = "2025-08-07T08:25:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c5/9c1f03121ece6634818490bd3c8be2c82a70928a19de03467fb25a3ae2a8/rpds_py-0.27.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:92f3b3ec3e6008a1fe00b7c0946a170f161ac00645cde35e3c9a68c2475e8156", size = 400405, upload-time = "2025-08-07T08:25:14.417Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b8/e25d54af3e63ac94f0c16d8fe143779fe71ff209445a0c00d0f6984b6b2c/rpds_py-0.27.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1b3db5fae5cbce2131b7420a3f83553d4d89514c03d67804ced36161fe8b6b2", size = 413179, upload-time = "2025-08-07T08:25:15.664Z" }, + { url = "https://files.pythonhosted.org/packages/f9/d1/406b3316433fe49c3021546293a04bc33f1478e3ec7950215a7fce1a1208/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5355527adaa713ab693cbce7c1e0ec71682f599f61b128cf19d07e5c13c9b1f1", size = 556895, upload-time = "2025-08-07T08:25:17.061Z" }, + { url = "https://files.pythonhosted.org/packages/5f/bc/3697c0c21fcb9a54d46ae3b735eb2365eea0c2be076b8f770f98e07998de/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fcc01c57ce6e70b728af02b2401c5bc853a9e14eb07deda30624374f0aebfe42", size = 585464, upload-time = "2025-08-07T08:25:18.406Z" }, + { url = "https://files.pythonhosted.org/packages/63/09/ee1bb5536f99f42c839b177d552f6114aa3142d82f49cef49261ed28dbe0/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3001013dae10f806380ba739d40dee11db1ecb91684febb8406a87c2ded23dae", size = 555090, upload-time = "2025-08-07T08:25:20.461Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2c/363eada9e89f7059199d3724135a86c47082cbf72790d6ba2f336d146ddb/rpds_py-0.27.0-cp314-cp314t-win32.whl", hash = "sha256:0f401c369186a5743694dd9fc08cba66cf70908757552e1f714bfc5219c655b5", size = 218001, upload-time = "2025-08-07T08:25:21.761Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3f/d6c216ed5199c9ef79e2a33955601f454ed1e7420a93b89670133bca5ace/rpds_py-0.27.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1dca5507fa1337f75dcd5070218b20bc68cf8844271c923c1b79dfcbc20391", size = 230993, upload-time = "2025-08-07T08:25:23.34Z" }, +] + +[[package]] +name = "rsa" +version = "4.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, +] + +[[package]] +name = "s3transfer" +version = "0.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "botocore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/05/d52bf1e65044b4e5e27d4e63e8d1579dbdec54fce685908ae09bc3720030/s3transfer-0.13.1.tar.gz", hash = "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf", size = 150589, upload-time = "2025-07-18T19:22:42.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl", hash = "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724", size = 85308, upload-time = "2025-07-18T19:22:40.947Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "sse-starlette" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/6f/22ed6e33f8a9e76ca0a412405f31abb844b779d52c5f96660766edcd737c/sse_starlette-3.0.2.tar.gz", hash = "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a", size = 20985, upload-time = "2025-07-27T09:07:44.565Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/10/c78f463b4ef22eef8491f218f692be838282cd65480f6e423d7730dfd1fb/sse_starlette-3.0.2-py3-none-any.whl", hash = "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", size = 11297, upload-time = "2025-07-27T09:07:43.268Z" }, +] + +[[package]] +name = "starlette" +version = "0.47.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/15/b9/cc3017f9a9c9b6e27c5106cc10cc7904653c3eec0729793aec10479dd669/starlette-0.47.3.tar.gz", hash = "sha256:6bc94f839cc176c4858894f1f8908f0ab79dfec1a6b8402f6da9be26ebea52e9", size = 2584144, upload-time = "2025-08-24T13:36:42.122Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/fd/901cfa59aaa5b30a99e16876f11abe38b59a1a2c51ffb3d7142bb6089069/starlette-0.47.3-py3-none-any.whl", hash = "sha256:89c0778ca62a76b826101e7c709e70680a1699ca7da6b44d38eb0a7e61fe4b51", size = 72991, upload-time = "2025-08-24T13:36:40.887Z" }, +] + +[[package]] +name = "temporalio" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nexus-rpc" }, + { name = "protobuf" }, + { name = "types-protobuf" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/a7/622047cb731a104e455687793d724ed143925e9ea14b522ad5ce224e8d7f/temporalio-1.17.0.tar.gz", hash = "sha256:1ac8f1ade36fafe7110b979b6a16d89203e1f4fb9c874f2fe3b5d83c17b13244", size = 1734067, upload-time = "2025-09-03T01:27:05.205Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/9a/f6fd68e60afc67c402c0676c12baba3aa04d522c74f4123ed31b544d4159/temporalio-1.17.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:7a86948c74a872b7f5ecb51c5d7e8013fdda4d6a220fe92185629342e94393e7", size = 12905249, upload-time = "2025-09-03T01:26:51.93Z" }, + { url = "https://files.pythonhosted.org/packages/8c/7e/54cffb6a0ef4853f51bcefe5a74508940bad72a4442e50b3d52379a941c3/temporalio-1.17.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:00b34a986012a355bdadf0e7eb9e57e176f2e0b1d69ea4be9eb73c21672e7fd0", size = 12539749, upload-time = "2025-09-03T01:26:54.854Z" }, + { url = "https://files.pythonhosted.org/packages/ec/f3/e4c829eb31bdb5eb14411ce7765b4ad8087794231110ff6188497859f0e6/temporalio-1.17.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36a84e52727e287e13777d86fa0bbda11ba6523f75a616b811cc9d799b37b98c", size = 12969855, upload-time = "2025-09-03T01:26:57.464Z" }, + { url = "https://files.pythonhosted.org/packages/95/26/fef412e10408e35888815ac06c0c777cff1faa76157d861878d23a17edf0/temporalio-1.17.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:617f37edce3db97cc7d2ff81c145a1b92c100f6e0e42207739271d10c2eea38e", size = 13165153, upload-time = "2025-09-03T01:27:00.285Z" }, + { url = "https://files.pythonhosted.org/packages/58/2d/01d164b78ea414f1e2554cd9959ffcf95f0c91a6d595f03128a70e433f57/temporalio-1.17.0-cp39-abi3-win_amd64.whl", hash = "sha256:f2724220fda1fd5948d917350ac25069c62624f46e53d4d6c6171baa75681145", size = 13178439, upload-time = "2025-09-03T01:27:02.855Z" }, +] + +[[package]] +name = "tenacity" +version = "9.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, +] + +[[package]] +name = "tokenizers" +version = "0.21.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/2f/402986d0823f8d7ca139d969af2917fefaa9b947d1fb32f6168c509f2492/tokenizers-0.21.4.tar.gz", hash = "sha256:fa23f85fbc9a02ec5c6978da172cdcbac23498c3ca9f3645c5c68740ac007880", size = 351253, upload-time = "2025-07-28T15:48:54.325Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/c6/fdb6f72bf6454f52eb4a2510be7fb0f614e541a2554d6210e370d85efff4/tokenizers-0.21.4-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:2ccc10a7c3bcefe0f242867dc914fc1226ee44321eb618cfe3019b5df3400133", size = 2863987, upload-time = "2025-07-28T15:48:44.877Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a6/28975479e35ddc751dc1ddc97b9b69bf7fcf074db31548aab37f8116674c/tokenizers-0.21.4-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:5e2f601a8e0cd5be5cc7506b20a79112370b9b3e9cb5f13f68ab11acd6ca7d60", size = 2732457, upload-time = "2025-07-28T15:48:43.265Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8f/24f39d7b5c726b7b0be95dca04f344df278a3fe3a4deb15a975d194cbb32/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b376f5a1aee67b4d29032ee85511bbd1b99007ec735f7f35c8a2eb104eade5", size = 3012624, upload-time = "2025-07-28T13:22:43.895Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/26358925717687a58cb74d7a508de96649544fad5778f0cd9827398dc499/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2107ad649e2cda4488d41dfd031469e9da3fcbfd6183e74e4958fa729ffbf9c6", size = 2939681, upload-time = "2025-07-28T13:22:47.499Z" }, + { url = "https://files.pythonhosted.org/packages/99/6f/cc300fea5db2ab5ddc2c8aea5757a27b89c84469899710c3aeddc1d39801/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c73012da95afafdf235ba80047699df4384fdc481527448a078ffd00e45a7d9", size = 3247445, upload-time = "2025-07-28T15:48:39.711Z" }, + { url = "https://files.pythonhosted.org/packages/be/bf/98cb4b9c3c4afd8be89cfa6423704337dc20b73eb4180397a6e0d456c334/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f23186c40395fc390d27f519679a58023f368a0aad234af145e0f39ad1212732", size = 3428014, upload-time = "2025-07-28T13:22:49.569Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/96c1cc780e6ca7f01a57c13235dd05b7bc1c0f3588512ebe9d1331b5f5ae/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc88bb34e23a54cc42713d6d98af5f1bf79c07653d24fe984d2d695ba2c922a2", size = 3193197, upload-time = "2025-07-28T13:22:51.471Z" }, + { url = "https://files.pythonhosted.org/packages/f2/90/273b6c7ec78af547694eddeea9e05de771278bd20476525ab930cecaf7d8/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51b7eabb104f46c1c50b486520555715457ae833d5aee9ff6ae853d1130506ff", size = 3115426, upload-time = "2025-07-28T15:48:41.439Z" }, + { url = "https://files.pythonhosted.org/packages/91/43/c640d5a07e95f1cf9d2c92501f20a25f179ac53a4f71e1489a3dcfcc67ee/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:714b05b2e1af1288bd1bc56ce496c4cebb64a20d158ee802887757791191e6e2", size = 9089127, upload-time = "2025-07-28T15:48:46.472Z" }, + { url = "https://files.pythonhosted.org/packages/44/a1/dd23edd6271d4dca788e5200a807b49ec3e6987815cd9d0a07ad9c96c7c2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1340ff877ceedfa937544b7d79f5b7becf33a4cfb58f89b3b49927004ef66f78", size = 9055243, upload-time = "2025-07-28T15:48:48.539Z" }, + { url = "https://files.pythonhosted.org/packages/21/2b/b410d6e9021c4b7ddb57248304dc817c4d4970b73b6ee343674914701197/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3c1f4317576e465ac9ef0d165b247825a2a4078bcd01cba6b54b867bdf9fdd8b", size = 9298237, upload-time = "2025-07-28T15:48:50.443Z" }, + { url = "https://files.pythonhosted.org/packages/b7/0a/42348c995c67e2e6e5c89ffb9cfd68507cbaeb84ff39c49ee6e0a6dd0fd2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:c212aa4e45ec0bb5274b16b6f31dd3f1c41944025c2358faaa5782c754e84c24", size = 9461980, upload-time = "2025-07-28T15:48:52.325Z" }, + { url = "https://files.pythonhosted.org/packages/3d/d3/dacccd834404cd71b5c334882f3ba40331ad2120e69ded32cf5fda9a7436/tokenizers-0.21.4-cp39-abi3-win32.whl", hash = "sha256:6c42a930bc5f4c47f4ea775c91de47d27910881902b0f20e4990ebe045a415d0", size = 2329871, upload-time = "2025-07-28T15:48:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/41/f2/fd673d979185f5dcbac4be7d09461cbb99751554ffb6718d0013af8604cb/tokenizers-0.21.4-cp39-abi3-win_amd64.whl", hash = "sha256:475d807a5c3eb72c59ad9b5fcdb254f6e17f53dfcbb9903233b0dfa9c943b597", size = 2507568, upload-time = "2025-07-28T15:48:55.456Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, +] + +[[package]] +name = "tqdm" +version = "4.67.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, +] + +[[package]] +name = "trove-classifiers" +version = "2025.8.6.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/21/707af14daa638b0df15b5d5700349e0abdd3e5140069f9ab6e0ccb922806/trove_classifiers-2025.8.6.13.tar.gz", hash = "sha256:5a0abad839d2ed810f213ab133d555d267124ddea29f1d8a50d6eca12a50ae6e", size = 16932, upload-time = "2025-08-06T13:26:26.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/44/323a87d78f04d5329092aada803af3612dd004a64b69ba8b13046601a8c9/trove_classifiers-2025.8.6.13-py3-none-any.whl", hash = "sha256:c4e7fc83012770d80b3ae95816111c32b085716374dccee0d3fbf5c235495f9f", size = 14121, upload-time = "2025-08-06T13:26:25.063Z" }, +] + +[[package]] +name = "types-protobuf" +version = "6.30.2.20250822" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/68/0c7144be5c6dc16538e79458839fc914ea494481c7e64566de4ecc0c3682/types_protobuf-6.30.2.20250822.tar.gz", hash = "sha256:faacbbe87bd8cba4472361c0bd86f49296bd36f7761e25d8ada4f64767c1bde9", size = 62379, upload-time = "2025-08-22T03:01:56.572Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/64/b926a6355993f712d7828772e42b9ae942f2d306d25072329805c374e729/types_protobuf-6.30.2.20250822-py3-none-any.whl", hash = "sha256:5584c39f7e36104b5f8bdfd31815fa1d5b7b3455a79ddddc097b62320f4b1841", size = 76523, upload-time = "2025-08-22T03:01:55.157Z" }, +] + +[[package]] +name = "types-requests" +version = "2.32.4.20250809" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/b0/9355adb86ec84d057fea765e4c49cce592aaf3d5117ce5609a95a7fc3dac/types_requests-2.32.4.20250809.tar.gz", hash = "sha256:d8060de1c8ee599311f56ff58010fb4902f462a1470802cf9f6ed27bc46c4df3", size = 23027, upload-time = "2025-08-09T03:17:10.664Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/6f/ec0012be842b1d888d46884ac5558fd62aeae1f0ec4f7a581433d890d4b5/types_requests-2.32.4.20250809-py3-none-any.whl", hash = "sha256:f73d1832fb519ece02c85b1f09d5f0dd3108938e7d47e7f94bbfa18a6782b163", size = 20644, upload-time = "2025-08-09T03:17:09.716Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "uv-dynamic-versioning" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dunamai" }, + { name = "hatchling" }, + { name = "jinja2" }, + { name = "tomlkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/5e/f8cb4f05228225c9dfa27bc64e50247dd111dbdb7838aab59ef2ea70ea7b/uv_dynamic_versioning-0.11.0.tar.gz", hash = "sha256:0dc2aac525d7db15a69b4f1317040d2fd7df71d1f1ae7171cb85080c2b998c23", size = 39733, upload-time = "2025-08-22T10:11:03.765Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/07/4e11e21d0e9a9b801414ce7fb76f15a9888b1ea6df3112a4842065801c7f/uv_dynamic_versioning-0.11.0-py3-none-any.whl", hash = "sha256:954d50391820929ebcc5842284e04dd75f21ba9d5f47913426068eb883100122", size = 10909, upload-time = "2025-08-22T10:11:02.585Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + +[[package]] +name = "wrapt" +version = "1.17.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, + { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, + { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, + { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, + { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, + { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, + { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, + { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, + { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, + { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, + { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" }, + { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" }, + { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" }, + { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" }, + { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" }, + { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" }, + { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" }, + { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" }, + { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" }, + { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" }, + { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" }, + { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" }, + { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, + { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, + { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, +] + +[[package]] +name = "yarl" +version = "1.20.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/fb/efaa23fa4e45537b827620f04cf8f3cd658b76642205162e072703a5b963/yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac", size = 186428, upload-time = "2025-06-10T00:46:09.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/9a/cb7fad7d73c69f296eda6815e4a2c7ed53fc70c2f136479a91c8e5fbdb6d/yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9", size = 133667, upload-time = "2025-06-10T00:43:44.369Z" }, + { url = "https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a", size = 91025, upload-time = "2025-06-10T00:43:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/50/ec/72991ae51febeb11a42813fc259f0d4c8e0507f2b74b5514618d8b640365/yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2", size = 89709, upload-time = "2025-06-10T00:43:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/99/da/4d798025490e89426e9f976702e5f9482005c548c579bdae792a4c37769e/yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee", size = 352287, upload-time = "2025-06-10T00:43:49.924Z" }, + { url = "https://files.pythonhosted.org/packages/1a/26/54a15c6a567aac1c61b18aa0f4b8aa2e285a52d547d1be8bf48abe2b3991/yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819", size = 345429, upload-time = "2025-06-10T00:43:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/d6/95/9dcf2386cb875b234353b93ec43e40219e14900e046bf6ac118f94b1e353/yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16", size = 365429, upload-time = "2025-06-10T00:43:53.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/b2/33a8750f6a4bc224242a635f5f2cff6d6ad5ba651f6edcccf721992c21a0/yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6", size = 363862, upload-time = "2025-06-10T00:43:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd", size = 355616, upload-time = "2025-06-10T00:43:58.056Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f666894aa947a371724ec7cd2e5daa78ee8a777b21509b4252dd7bd15e29/yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a", size = 339954, upload-time = "2025-06-10T00:43:59.773Z" }, + { url = "https://files.pythonhosted.org/packages/f1/81/5f466427e09773c04219d3450d7a1256138a010b6c9f0af2d48565e9ad13/yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38", size = 365575, upload-time = "2025-06-10T00:44:02.051Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e3/e4b0ad8403e97e6c9972dd587388940a032f030ebec196ab81a3b8e94d31/yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef", size = 365061, upload-time = "2025-06-10T00:44:04.196Z" }, + { url = "https://files.pythonhosted.org/packages/ac/99/b8a142e79eb86c926f9f06452eb13ecb1bb5713bd01dc0038faf5452e544/yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f", size = 364142, upload-time = "2025-06-10T00:44:06.527Z" }, + { url = "https://files.pythonhosted.org/packages/34/f2/08ed34a4a506d82a1a3e5bab99ccd930a040f9b6449e9fd050320e45845c/yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8", size = 381894, upload-time = "2025-06-10T00:44:08.379Z" }, + { url = "https://files.pythonhosted.org/packages/92/f8/9a3fbf0968eac704f681726eff595dce9b49c8a25cd92bf83df209668285/yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a", size = 383378, upload-time = "2025-06-10T00:44:10.51Z" }, + { url = "https://files.pythonhosted.org/packages/af/85/9363f77bdfa1e4d690957cd39d192c4cacd1c58965df0470a4905253b54f/yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004", size = 374069, upload-time = "2025-06-10T00:44:12.834Z" }, + { url = "https://files.pythonhosted.org/packages/35/99/9918c8739ba271dcd935400cff8b32e3cd319eaf02fcd023d5dcd487a7c8/yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5", size = 81249, upload-time = "2025-06-10T00:44:14.731Z" }, + { url = "https://files.pythonhosted.org/packages/eb/83/5d9092950565481b413b31a23e75dd3418ff0a277d6e0abf3729d4d1ce25/yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698", size = 86710, upload-time = "2025-06-10T00:44:16.716Z" }, + { url = "https://files.pythonhosted.org/packages/8a/e1/2411b6d7f769a07687acee88a062af5833cf1966b7266f3d8dfb3d3dc7d3/yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a", size = 131811, upload-time = "2025-06-10T00:44:18.933Z" }, + { url = "https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3", size = 90078, upload-time = "2025-06-10T00:44:20.635Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9a/3246ae92d4049099f52d9b0fe3486e3b500e29b7ea872d0f152966fc209d/yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7", size = 88748, upload-time = "2025-06-10T00:44:22.34Z" }, + { url = "https://files.pythonhosted.org/packages/a3/25/35afe384e31115a1a801fbcf84012d7a066d89035befae7c5d4284df1e03/yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691", size = 349595, upload-time = "2025-06-10T00:44:24.314Z" }, + { url = "https://files.pythonhosted.org/packages/28/2d/8aca6cb2cabc8f12efcb82749b9cefecbccfc7b0384e56cd71058ccee433/yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31", size = 342616, upload-time = "2025-06-10T00:44:26.167Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e9/1312633d16b31acf0098d30440ca855e3492d66623dafb8e25b03d00c3da/yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28", size = 361324, upload-time = "2025-06-10T00:44:27.915Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a0/688cc99463f12f7669eec7c8acc71ef56a1521b99eab7cd3abb75af887b0/yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653", size = 359676, upload-time = "2025-06-10T00:44:30.041Z" }, + { url = "https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5", size = 352614, upload-time = "2025-06-10T00:44:32.171Z" }, + { url = "https://files.pythonhosted.org/packages/b1/91/31163295e82b8d5485d31d9cf7754d973d41915cadce070491778d9c9825/yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02", size = 336766, upload-time = "2025-06-10T00:44:34.494Z" }, + { url = "https://files.pythonhosted.org/packages/b4/8e/c41a5bc482121f51c083c4c2bcd16b9e01e1cf8729e380273a952513a21f/yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53", size = 364615, upload-time = "2025-06-10T00:44:36.856Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5b/61a3b054238d33d70ea06ebba7e58597891b71c699e247df35cc984ab393/yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc", size = 360982, upload-time = "2025-06-10T00:44:39.141Z" }, + { url = "https://files.pythonhosted.org/packages/df/a3/6a72fb83f8d478cb201d14927bc8040af901811a88e0ff2da7842dd0ed19/yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04", size = 369792, upload-time = "2025-06-10T00:44:40.934Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/4cc3c36dfc7c077f8dedb561eb21f69e1e9f2456b91b593882b0b18c19dc/yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4", size = 382049, upload-time = "2025-06-10T00:44:42.854Z" }, + { url = "https://files.pythonhosted.org/packages/19/3a/e54e2c4752160115183a66dc9ee75a153f81f3ab2ba4bf79c3c53b33de34/yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b", size = 384774, upload-time = "2025-06-10T00:44:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/200ae86dabfca89060ec6447649f219b4cbd94531e425e50d57e5f5ac330/yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1", size = 374252, upload-time = "2025-06-10T00:44:47.31Z" }, + { url = "https://files.pythonhosted.org/packages/83/75/11ee332f2f516b3d094e89448da73d557687f7d137d5a0f48c40ff211487/yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7", size = 81198, upload-time = "2025-06-10T00:44:49.164Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c", size = 86346, upload-time = "2025-06-10T00:44:51.182Z" }, + { url = "https://files.pythonhosted.org/packages/43/c7/669c52519dca4c95153c8ad96dd123c79f354a376346b198f438e56ffeb4/yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d", size = 138826, upload-time = "2025-06-10T00:44:52.883Z" }, + { url = "https://files.pythonhosted.org/packages/6a/42/fc0053719b44f6ad04a75d7f05e0e9674d45ef62f2d9ad2c1163e5c05827/yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf", size = 93217, upload-time = "2025-06-10T00:44:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/4f/7f/fa59c4c27e2a076bba0d959386e26eba77eb52ea4a0aac48e3515c186b4c/yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3", size = 92700, upload-time = "2025-06-10T00:44:56.784Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/062b2f48e7c93481e88eff97a6312dca15ea200e959f23e96d8ab898c5b8/yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d", size = 347644, upload-time = "2025-06-10T00:44:59.071Z" }, + { url = "https://files.pythonhosted.org/packages/89/47/78b7f40d13c8f62b499cc702fdf69e090455518ae544c00a3bf4afc9fc77/yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c", size = 323452, upload-time = "2025-06-10T00:45:01.605Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2b/490d3b2dc66f52987d4ee0d3090a147ea67732ce6b4d61e362c1846d0d32/yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1", size = 346378, upload-time = "2025-06-10T00:45:03.946Z" }, + { url = "https://files.pythonhosted.org/packages/66/ad/775da9c8a94ce925d1537f939a4f17d782efef1f973039d821cbe4bcc211/yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce", size = 353261, upload-time = "2025-06-10T00:45:05.992Z" }, + { url = "https://files.pythonhosted.org/packages/4b/23/0ed0922b47a4f5c6eb9065d5ff1e459747226ddce5c6a4c111e728c9f701/yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3", size = 335987, upload-time = "2025-06-10T00:45:08.227Z" }, + { url = "https://files.pythonhosted.org/packages/3e/49/bc728a7fe7d0e9336e2b78f0958a2d6b288ba89f25a1762407a222bf53c3/yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be", size = 329361, upload-time = "2025-06-10T00:45:10.11Z" }, + { url = "https://files.pythonhosted.org/packages/93/8f/b811b9d1f617c83c907e7082a76e2b92b655400e61730cd61a1f67178393/yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16", size = 346460, upload-time = "2025-06-10T00:45:12.055Z" }, + { url = "https://files.pythonhosted.org/packages/70/fd/af94f04f275f95da2c3b8b5e1d49e3e79f1ed8b6ceb0f1664cbd902773ff/yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513", size = 334486, upload-time = "2025-06-10T00:45:13.995Z" }, + { url = "https://files.pythonhosted.org/packages/84/65/04c62e82704e7dd0a9b3f61dbaa8447f8507655fd16c51da0637b39b2910/yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f", size = 342219, upload-time = "2025-06-10T00:45:16.479Z" }, + { url = "https://files.pythonhosted.org/packages/91/95/459ca62eb958381b342d94ab9a4b6aec1ddec1f7057c487e926f03c06d30/yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390", size = 350693, upload-time = "2025-06-10T00:45:18.399Z" }, + { url = "https://files.pythonhosted.org/packages/a6/00/d393e82dd955ad20617abc546a8f1aee40534d599ff555ea053d0ec9bf03/yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458", size = 355803, upload-time = "2025-06-10T00:45:20.677Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ed/c5fb04869b99b717985e244fd93029c7a8e8febdfcffa06093e32d7d44e7/yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e", size = 341709, upload-time = "2025-06-10T00:45:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/24/fd/725b8e73ac2a50e78a4534ac43c6addf5c1c2d65380dd48a9169cc6739a9/yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d", size = 86591, upload-time = "2025-06-10T00:45:25.793Z" }, + { url = "https://files.pythonhosted.org/packages/94/c3/b2e9f38bc3e11191981d57ea08cab2166e74ea770024a646617c9cddd9f6/yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f", size = 93003, upload-time = "2025-06-10T00:45:27.752Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2d/2345fce04cfd4bee161bf1e7d9cdc702e3e16109021035dbb24db654a622/yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77", size = 46542, upload-time = "2025-06-10T00:46:07.521Z" }, +] + +[[package]] +name = "zipp" +version = "3.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, +] diff --git a/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json b/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json new file mode 100644 index 0000000000..e1c79d1d7e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json @@ -0,0 +1,51 @@ +{ + "name": "departments_flat", + "fields": [ + { + "name": "id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": true, + "synonymMaps": [] + }, + { + "name": "department", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "description", + "type": "Edm.String", + "searchable": true, + "filterable": false, + "retrievable": true, + "stored": true, + "sortable": false, + "facetable": false, + "key": false, + "synonymMaps": [] + } + ], + "scoringProfiles": [], + "suggesters": [], + "analyzers": [], + "normalizers": [], + "tokenizers": [], + "tokenFilters": [], + "charFilters": [], + "similarity": { + "@odata.type": "#Microsoft.Azure.Search.BM25Similarity" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json b/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json new file mode 100644 index 0000000000..f1c36bbd2c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json @@ -0,0 +1,75 @@ +{ + "name": "net_sales", + "fields": [ + { + "name": "id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": true, + "synonymMaps": [] + }, + { + "name": "sku_id", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "net_sales", + "type": "Edm.Double", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "name", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "department", + "type": "Edm.String", + "searchable": true, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + } + ], + "scoringProfiles": [], + "suggesters": [], + "analyzers": [], + "normalizers": [], + "tokenizers": [], + "tokenFilters": [], + "charFilters": [], + "similarity": { + "@odata.type": "#Microsoft.Azure.Search.BM25Similarity" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json b/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json new file mode 100644 index 0000000000..dd91605c9f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json @@ -0,0 +1,99 @@ +{ + "name": "product_inventory", + "fields": [ + { + "name": "id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": true, + "synonymMaps": [] + }, + { + "name": "sku_id", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": false, + "synonymMaps": [] + }, + { + "name": "inventory_level", + "type": "Edm.Double", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "unit_price", + "type": "Edm.Double", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + }, + { + "name": "name", + "type": "Edm.String", + "searchable": true, + "filterable": false, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": false, + "key": false, + "synonymMaps": [] + }, + { + "name": "description", + "type": "Edm.String", + "searchable": true, + "filterable": false, + "retrievable": true, + "stored": true, + "sortable": false, + "facetable": false, + "key": false, + "synonymMaps": [] + }, + { + "name": "department", + "type": "Edm.String", + "searchable": false, + "filterable": true, + "retrievable": true, + "stored": true, + "sortable": true, + "facetable": true, + "key": false, + "synonymMaps": [] + } + ], + "scoringProfiles": [], + "suggesters": [], + "analyzers": [], + "normalizers": [], + "tokenizers": [], + "tokenFilters": [], + "charFilters": [], + "similarity": { + "@odata.type": "#Microsoft.Azure.Search.BM25Similarity" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh b/073-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh new file mode 100755 index 0000000000..10227bac7d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# This script creates the necessary indices in Azure AI Search +# It assumes that the CURL CLI is installed, configured, and the user is authenticated. +# It also assumes that the user has the necessary permissions (ADMIN API KEY) to create indices. + +AI_SEARCH_API_VERSION="2025-03-01-Preview" + +create_ai_search_index() +{ + # Get the index name from the first argument + INDEX_NAME="$1" + # Get the index schema from the second argument + INDEX_SCHEMA="./ai-search-schemas/${INDEX_NAME}.json" + # Get the search service name from the third argument + SEARCH_SERVICE_NAME="${AZURE_SEARCH_SERVICE_NAME}" + # Get the resource group name from the fourth argument + RESOURCE_GROUP="$4" + + # Create the index using the REST API endpoint + echo "" + echo "Creating index ${INDEX_NAME} in Azure AI Search service ${SEARCH_SERVICE_NAME}..." + # Use curl to send a PUT request to create the index + # Ensure the index schema file exists + if [ ! -f "${INDEX_SCHEMA}" ]; then + echo "Error: Index schema file ${INDEX_SCHEMA} does not exist." + exit 1 + fi + + # Use curl to send a PUT request to create the index + curl -X PUT \ + "https://${SEARCH_SERVICE_NAME}.search.windows.net/indexes/${INDEX_NAME}?api-version=${AI_SEARCH_API_VERSION}" \ + -H "Content-Type: application/json" \ + -H "api-key: ${AZURE_SEARCH_API_KEY}" \ + -d "@${INDEX_SCHEMA}" + + # Check if the index creation was successful + if [ $? -eq 0 ]; then + echo "Index ${INDEX_NAME} created successfully." + else + echo "Failed to create index ${INDEX_NAME}." + fi + + echo "" + echo "Done creating index ${INDEX_NAME} in Azure AI Search service ${SEARCH_SERVICE_NAME}..." + echo "" + echo "----------------------------------------------" + echo "" +} + +# List AI Search indices +# This will show all indices before creation +list_ai_search_indices() { + echo "" + echo "Listing all indices in Azure AI Search service ${AZURE_SEARCH_SERVICE_NAME}..." + + # Use curl to send a GET request and pipe output to jq for pretty-printing + response=$(curl -s -X GET \ + "https://${AZURE_SEARCH_SERVICE_NAME}.search.windows.net/indexes?api-version=${AI_SEARCH_API_VERSION}" \ + -H "Content-Type: application/json" \ + -H "api-key: ${AZURE_SEARCH_API_KEY}") + + # Check if curl executed successfully + if [ $? -eq 0 ]; then + echo "Listed all indices successfully." + echo "$response" | jq . + else + echo "Failed to list indices." + fi + + echo "" + echo "Done listing all indices in Azure AI Search service ${AZURE_SEARCH_SERVICE_NAME}..." + echo "" + echo "----------------------------------------------" + echo "" +} + + +# List all indices in the Azure AI Search service +list_ai_search_indices + +# Create the indices in Azure AI Search +create_ai_search_index "net_sales" +create_ai_search_index "product_inventory" + +# List all indices in the Azure AI Search service again +list_ai_search_indices + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml b/073-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml new file mode 100755 index 0000000000..fd6dd2abb3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml @@ -0,0 +1,34 @@ +--- +# Run the following commands to start the compose file +# docker-compose up + +# Run the following command to stop the compose file +# docker-compose down --remove-orphans + +networks: + default: + name: confluent_streams + driver: bridge + +services: + inventory: + image: izzyacademy/inventory:latest + env_file: [shared_environment_variables.env] + hostname: inventory + ports: ["8080:8080"] + + replenishment: + image: izzyacademy/replenishment:latest + env_file: [shared_environment_variables.env] + hostname: replenishment + ports: ["8081:8081"] + + employee: + image: izzyacademy/employee:latest + env_file: [shared_environment_variables.env] + hostname: employee + + supplier: + image: izzyacademy/supplier:latest + env_file: [shared_environment_variables.env] + hostname: supplier \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example b/073-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example new file mode 100755 index 0000000000..bc45c0d333 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example @@ -0,0 +1,32 @@ +# Azure Service Principal +AZURE_SUBSCRIPTION_ID=enter-your-subscription-id-here +AZURE_CLIENT_ID=enter-your-client-id-here +AZURE_CLIENT_SECRET=enter-your-client-secret-here +AZURE_TENANT_ID=enter-your-tenant-id-here + +# Azure AI Search +AZURE_AI_SEARCH_API_VERSION=2025-03-01-preview # keep or change as needed +AZURE_AI_SEARCH_ENDPOINT=https://your-search-service.search.windows.net +AZURE_AI_SEARCH_API_KEY=enter-your-ai-search-api-key-here + +# Azure Cosmos DB +COSMOS_CONNECTION_STRING=AccountEndpoint=https://your-cosmos-account.documents.azure.com:443/;AccountKey=enter-your-cosmos-key-here; +COSMOS_ENDPOINT=https://your-cosmos-account.documents.azure.com:443/ +COSMOS_DATABASE_NAME=enter-your-database-name-here + +# Azure Redis Cache +REDIS_HOST=your-redis-cache-name.redis.cache.windows.net +REDIS_PORT=6380 +REDIS_PASSWORD=enter-your-redis-password-here + +# Azure OpenAI (AI Foundry) +AZURE_OPENAI_ENDPOINT=https://your-openai-resource.openai.azure.com/ +AZURE_OPENAI_API_KEY=enter-your-openai-api-key-here +AZURE_OPENAI_MODEL_NAME=gpt-4o-mini +OPENAI_API_VERSION=2025-01-01-preview + +# MCP Services +# Adjust the below endpoint HTTP schemes, hostnames and ports as necessary for your setup +MCP_SERVICE_ENDPOINT_INVENTORY=http://inventory:8080/mcp +MCP_SERVICE_ENDPOINT_REPLENISHMENT=http://replenishment:8081/mcp +MCP_SERVICE_ENDPOINT_SHOPPING=http://shopping:8082/mcp diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh new file mode 100755 index 0000000000..947ff93fc6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Authenticate with Confluent Cloud CLI +# https://docs.confluent.io/cloud/current/cli/install.html +# Ensure you have the Confluent CLI installed and configured +confluent login + +confluent environment use "${CONFLUENT_ENVIRONMENT_ID}" + +# Ensure the Cluster Region matches the Azure Region +confluent kafka cluster use "${KAFKA_ID}" + +# Ensure the Flink Compute Pool Region matches the Azure Region +confluent flink compute-pool use "${FLINK_COMPUTE_POOL_ID}" + +confluent api-key store --force "${CONFLUENT_CLOUD_API_KEY}" "${CONFLUENT_CLOUD_API_SECRET}" +confluent api-key store --force "${KAFKA_API_KEY}" "${KAFKA_API_SECRET}" + +confluent api-key use "${KAFKA_API_KEY}" diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh new file mode 100755 index 0000000000..79b89fb790 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh @@ -0,0 +1,44 @@ + +# This script sets up a Confluent Connect cluster with the specified configuration file. + + +# Sets up a Confluent Connector using the provided configuration file. +setup_confluent_connector() +{ + local CONNECTOR_NAME="$1" + local CONNECTOR_CONFIG_DIRECTORY="./connector-configurations" + local CONNECTOR_CONFIG_FILE="${CONNECTOR_CONFIG_DIRECTORY}/${CONNECTOR_NAME}.final.json" + # Check if the connector configuration file exists + if [ ! -f "$CONNECTOR_CONFIG_FILE" ]; then + echo "Error: Connector configuration file $CONNECTOR_CONFIG_FILE does not exist." + exit 1 + fi + + # Create the connector using the provided configuration file + echo "" + echo "" + echo "Creating connector $CONNECTOR_NAME using configuration file $CONNECTOR_CONFIG_FILE..." + + # Create the Kafka Connector + confluent connect cluster create --config-file ${CONNECTOR_CONFIG_FILE} +} + + +# Create the Kafka Source Connectors for Azure Blob Storage +setup_confluent_connector "azure_blob_departments" +setup_confluent_connector "azure_blob_product_pricing" +setup_confluent_connector "azure_blob_product_skus" + + +# Set up the Kafka Sink Connectors for Azure Cosmos DB +setup_confluent_connector "cosmos_db_purchases" +setup_confluent_connector "cosmos_db_returns" +setup_confluent_connector "cosmos_db_replenishments" + +# Set up the Kafka Sink Connectors for Azure AI Search +setup_confluent_connector "ai_search_product_inventory" +setup_confluent_connector "ai_search_net_sales" +setup_confluent_connector "ai_search_departments_flat" + +# List all connectors in the cluster +confluent connect cluster list diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh new file mode 100755 index 0000000000..7dc64c53f3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# This script sets up the schemas for the Confluent Schema Registry. +# It creates the necessary topics and registers the schemas. +# Assumes that the Confluent CLI is installed, configured, and the user is authenticated. + +# Function to create a Kafka topic and register its key/value schemas +# Example usage +# create_topic_with_schema "sales_transactions" +create_topic_with_schema() { + + # Check if the topic name is provided + if [ -z "$1" ]; then + echo "Error: No topic name provided." + echo "Usage: create_topic_with_schema <topic_name>" + exit 1 + fi + + local topic_name="$1" # The name of the topic to create + local key_schema_file="./retail_store/${topic_name}/schemas/${topic_name}-key.json" # Path to the key schema file + local value_schema_file="./retail_store/${topic_name}/schemas/${topic_name}-value.json" # Path to the value schema file + + echo "" + echo "" + echo + echo "Creating topic: $topic_name" + confluent kafka topic create "$topic_name" --if-not-exists --partitions 6 + + echo "Registering value schema for subject: ${topic_name}-value" + confluent schema-registry schema create \ + --subject "${topic_name}-value" \ + --schema "$value_schema_file" \ + --type "json" + + echo "Registering key schema for subject: ${topic_name}-key" + confluent schema-registry schema create \ + --subject "${topic_name}-key" \ + --schema "$key_schema_file" \ + --type "json" + + echo "Verifying registered schemas for $topic_name" + confluent schema-registry schema list --subject-prefix "${topic_name}" + + echo "----------------------------------------------" + echo "Topic and schemas setup complete for: $topic_name" + echo "----------------------------------------------" + echo "" + echo "" +} + +# Set Kafka Topic Schema Registry Subject +set_schema_registry_subject_compatibility() { + local topic_name="$1" # The name of the topic to set compatibility for + local compatibility_level="$2" # The desired compatibility level. Can be "backward", "backward_transitive", "forward", "forward_transitive", "full", "full_transitive", or "none". + + local key_schema_subject="${topic_name}-key" + local value_schema_subject="${topic_name}-value" + + + echo "Setting schema registry topic key/value compatibility for $topic_name to $compatibility_level" + confluent schema-registry subject update ${key_schema_subject} --compatibility ${compatibility_level} + confluent schema-registry subject update ${value_schema_subject} --compatibility ${compatibility_level} + + echo "----------------------------------------------" + echo "Schema registry subject compatibility set for: $topic_name" + echo "----------------------------------------------" + +} + +# Reference topics from Azure Blob Store +create_topic_with_schema "departments" +create_topic_with_schema "product_pricing" +create_topic_with_schema "product_skus" + +# Transaction topics from Cosmos DB +create_topic_with_schema "purchases" +create_topic_with_schema "replenishments" +create_topic_with_schema "returns" + +# Transaction topics from Cosmos DB flattened +create_topic_with_schema "purchases_flat" +create_topic_with_schema "replenishments_flat" +create_topic_with_schema "returns_flat" + +# Destination topics heading over to Azure AI Search +create_topic_with_schema "net_sales" +create_topic_with_schema "product_inventory" +create_topic_with_schema "departments_flat" + +confluent schema-registry schema list + +# Set schema registry subject compatibility for cosomos db topics +set_schema_registry_subject_compatibility "purchases" "none" +set_schema_registry_subject_compatibility "replenishments" "none" +set_schema_registry_subject_compatibility "returns" "none" \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh new file mode 100755 index 0000000000..fc0adfee01 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# This script deletes specified connectors from a Confluent Kafka Connect cluster. +# It assumes that the Confluent CLI is installed, configured, and the user is authenticated. +# It also assumes that the user has the necessary permissions to delete connectors. +# Function to get connector IDs from their names + +# Example usage: +# get_connector_ids "azure_blob_product_pricing_source_connector,azure_cosmos_db_purchases_source,azure_cosmos_db_returns_source" +get_connector_ids() { + local connector_names_csv="$1" + local connector_names_array + + IFS=',' read -r -a connector_names_array <<< "$connector_names_csv" + + # Get current connectors JSON + local connectors_json + connectors_json=$(confluent connect cluster list -o json) + + # Initialize result + local connector_ids=() + + for name in "${connector_names_array[@]}"; do + id=$(echo "$connectors_json" | jq -r --arg NAME "$name" '.[] | select(.name == $NAME) | .id') + if [[ -n "$id" ]]; then + connector_ids+=("$id") + fi + done + + # Output space-delimited list + echo "${connector_ids[@]}" +} + +# List all connectors in the cluster +echo "Listing all connectors in the cluster before deletion:" +# This will show all connectors before deletion + +confluent connect cluster list + +echo "----------------------------------------------" +echo "Deleting specified connectors from the cluster:" + + +# These are the connector names to delete +connectors="ai_search_departments_sink,ai_search_net_sales_sink,ai_search_departments_flat_sink,ai_search_product_inventory_sink,azure_blob_product_pricing_source_connector,azure_cosmos_db_purchases_source,azure_blob_product_skus_source_connector,azure_cosmos_db_returns_source,azure_cosmos_db_replenishments_source,azure_blob_departments_source_connector" + +# Call the function +ids=$(get_connector_ids "$connectors") + +echo "Connector IDs: $ids" + +# Delete the connectors using their IDs +for id in $ids; do + echo "Deleting connector with ID: $id" + confluent connect cluster delete "$id" --force + # Check if the deletion was successful + # The exit status of the last command is stored in $? + # If the exit status is 0, the command was successful + # If the exit status is not 0, the command failed + if [ $? -eq 0 ]; then + echo "Connector with ID $id deleted successfully." + else + echo "Failed to delete connector with ID $id." + fi +done +echo "All specified connectors have been deleted." + +# List all connectors in the cluster +confluent connect cluster list +echo "All connectors in the cluster have been listed." +echo "----------------------------------------------" +echo "Confluent Connectors deletion complete." + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh new file mode 100755 index 0000000000..53cb944851 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +delete_topic_schemas() { + local topic_name="$1" # The name of the topic to delete + local topic_key_schema="${topic_name}-key" # The key schema subject + local topic_value_schema="${topic_name}-value" # The value schema subject + + # Check if the topic name is provided + if [ -z "$topic_name" ]; then + echo "Error: No topic name provided." + echo "Usage: delete_topic_schemas <topic_name>" + exit 1 + fi + + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force + + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force --permanent + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force --permanent + +} + + +# List Schema Registry +confluent schema-registry schema list + + +# Reference topics from Azure Blob Store +delete_topic_schemas "departments" +delete_topic_schemas "product_pricing" +delete_topic_schemas "product_skus" + +# Transaction topics from Cosmos DB +delete_topic_schemas "purchases" +delete_topic_schemas "replenishments" +delete_topic_schemas "returns" + +# Destination topics heading over to Azure AI Search +delete_topic_schemas "net_sales" +delete_topic_schemas "product_inventory" + +confluent schema-registry schema list \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh new file mode 100755 index 0000000000..2eca130fc8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh @@ -0,0 +1,49 @@ + + +# This script deletes all topics in the Confluent Cloud environment. +# It assumes that the Confluent CLI is installed, configured, and the user is authenticated. +# It also assumes that the user has the necessary permissions to delete topics. + +# Function to delete a Kafka topic and its associated schemas +# Example usage +# delete_kafka_topic "sales_transactions" +delete_kafka_topic_and_schemas() { + # Check if the topic name is provided + if [ -z "$1" ]; then + echo "Error: No topic name provided." + echo "Usage: delete_kafka_topic_and_schemas <topic_name>" + exit 1 + fi + + local topic_name="$1" # The name of the topic to delete + local topic_key_schema="${topic_name}-key" # The key schema subject + local topic_value_schema="${topic_name}-value" # The value schema subject + + # Delete the schemas associated with the topic + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force + + # Permanently delete the schemas + confluent schema-registry schema delete --subject $topic_key_schema --version "all" --force --permanent + confluent schema-registry schema delete --subject $topic_value_schema --version "all" --force --permanent + + # Delete the Kafka topic + confluent kafka topic delete "$topic_name" --force + echo "Topic $topic_name and its schemas have been deleted." +} + +# Reference topics from Azure Blob Store +delete_kafka_topic_and_schemas "departments" +delete_kafka_topic_and_schemas "product_pricing" +delete_kafka_topic_and_schemas "product_skus" + +# Transaction topics from Cosmos DB +delete_kafka_topic_and_schemas "purchases" +delete_kafka_topic_and_schemas "replenishments" +delete_kafka_topic_and_schemas "returns" + +# Destination topics heading over to Azure AI Search +delete_kafka_topic_and_schemas "net_sales" +delete_kafka_topic_and_schemas "product_inventory" + + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh new file mode 100755 index 0000000000..e69de29bb2 diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh new file mode 100755 index 0000000000..b61167e90c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +connector_config_populate_secrets() +{ + + + # Path to the input and output files + FILE_PREFIX="$1" + DIRECTORY_PREFIX="./connector-configurations" + INPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.example.json" + OUTPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.final.json" + + echo "" + echo "" + echo "Preparing Connector Configuration File ${FILE_PREFIX} ..." + # Replace placeholders and output to a new file + sed \ + -e "s|\[AZURE_RESOURCE_GROUP\]|${AZURE_RESOURCE_GROUP}|g" \ + -e "s|\[KAFKA_API_KEY\]|${KAFKA_API_KEY}|g" \ + -e "s|\[KAFKA_API_SECRET\]|${KAFKA_API_SECRET}|g" \ + -e "s|\[AZURE_SEARCH_SERVICE_NAME\]|${AZURE_SEARCH_SERVICE_NAME}|g" \ + -e "s|\[AZURE_SEARCH_API_KEY\]|${AZURE_SEARCH_API_KEY}|g" \ + -e "s|\[AZURE_STORAGE_ACCOUNT_NAME\]|${AZURE_STORAGE_ACCOUNT_NAME}|g" \ + -e "s|\[AZURE_STORAGE_ACCOUNT_KEY\]|${AZURE_STORAGE_ACCOUNT_KEY}|g" \ + -e "s|\[AZURE_COSMOS_DB_ACCOUNT_NAME\]|${AZURE_COSMOS_DB_ACCOUNT_NAME}|g" \ + -e "s|\[AZURE_COSMOS_DB_ACCOUNT_KEY\]|${AZURE_COSMOS_DB_ACCOUNT_KEY}|g" \ + -e "s|\[AZURE_COSMOS_DB_DATABASE_NAME\]|${AZURE_COSMOS_DB_DATABASE_NAME}|g" \ + -e "s|\[ARM_CLIENT_ID\]|${ARM_CLIENT_ID}|g" \ + -e "s|\[ARM_CLIENT_SECRET\]|${ARM_CLIENT_SECRET}|g" \ + -e "s|\[ARM_TENANT_ID\]|${ARM_TENANT_ID}|g" \ + -e "s|\[ARM_SUBSCRIPTION_ID\]|${ARM_SUBSCRIPTION_ID}|g" \ + "$INPUT_FILE" > "$OUTPUT_FILE" + + echo "Replacement complete. Modified file saved as $OUTPUT_FILE." +} + +connector_config_populate_secrets "ai_search_product_inventory" +connector_config_populate_secrets "ai_search_net_sales" +connector_config_populate_secrets "ai_search_departments_flat" + +connector_config_populate_secrets "azure_blob_departments" +connector_config_populate_secrets "azure_blob_product_skus" +connector_config_populate_secrets "azure_blob_product_pricing" + +connector_config_populate_secrets "cosmos_db_purchases" +connector_config_populate_secrets "cosmos_db_returns" +connector_config_populate_secrets "cosmos_db_replenishments" \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh new file mode 100755 index 0000000000..3ce16fa741 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +connector_config_reset() +{ + + + # Path to the input and output files + FILE_PREFIX="$1" + DIRECTORY_PREFIX="./connector-configurations" + INPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.example.json" + OUTPUT_FILE="${DIRECTORY_PREFIX}/${FILE_PREFIX}.final.json" + + echo "" + echo "Removing existing output file ${OUTPUT_FILE} if it exists..." + echo "Leaving Input file ${INPUT_FILE} intact..." + rm -v -f "$OUTPUT_FILE" + echo "" + +} + +connector_config_reset "ai_search_product_inventory" +connector_config_reset "ai_search_net_sales" +connector_config_reset "ai_search_departments_flat" + +connector_config_reset "azure_blob_departments" +connector_config_reset "azure_blob_product_skus" +connector_config_reset "azure_blob_product_pricing" + +connector_config_reset "cosmos_db_purchases" +connector_config_reset "cosmos_db_returns" +connector_config_reset "cosmos_db_replenishments" \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json new file mode 100644 index 0000000000..97ef41ad8b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json @@ -0,0 +1,36 @@ +{ + "config": { + "topics": "departments", + "schema.context.name": "default", + "input.data.format": "JSON_SR", + "connector.class": "AzureCognitiveSearchSink", + "name": "ai_search_departments_sink", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azure.search.service.name": "[AZURE_SEARCH_SERVICE_NAME]", + "azure.search.api.key": "[AZURE_SEARCH_API_KEY]", + "azure.search.client.id": "[ARM_CLIENT_ID]", + "azure.search.client.secret": "[ARM_CLIENT_SECRET]", + "azure.search.tenant.id": "[ARM_TENANT_ID]", + "azure.search.subscription.id": "[ARM_SUBSCRIPTION_ID]", + "azure.search.resourcegroup.name": "[AZURE_RESOURCE_GROUP]", + "index.name": "departments", + "write.method": "Upload", + "delete.enabled": "true", + "key.mode": "KEY", + "max.batch.size": "25", + "max.retry.ms": "300000", + "max.poll.interval.ms": "300000", + "max.poll.records": "500", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "transforms": "department_to_key", + "transforms.department_to_key.type": "org.apache.kafka.connect.transforms.ValueToKey", + "transforms.department_to_key.fields": "department" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json new file mode 100644 index 0000000000..8650fd2e80 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json @@ -0,0 +1,36 @@ +{ + "config": { + "topics": "net_sales", + "schema.context.name": "default", + "input.data.format": "JSON_SR", + "connector.class": "AzureCognitiveSearchSink", + "name": "ai_search_net_sales_sink", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azure.search.service.name": "[AZURE_SEARCH_SERVICE_NAME]", + "azure.search.api.key": "[AZURE_SEARCH_API_KEY]", + "azure.search.client.id": "[ARM_CLIENT_ID]", + "azure.search.client.secret": "[ARM_CLIENT_SECRET]", + "azure.search.tenant.id": "[ARM_TENANT_ID]", + "azure.search.subscription.id": "[ARM_SUBSCRIPTION_ID]", + "azure.search.resourcegroup.name": "[AZURE_RESOURCE_GROUP]", + "index.name": "net_sales", + "write.method": "Upload", + "delete.enabled": "true", + "key.mode": "KEY", + "max.batch.size": "25", + "max.retry.ms": "300000", + "max.poll.interval.ms": "300000", + "max.poll.records": "500", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "transforms": "sku_id_to_key", + "transforms.sku_id_to_key.type": "org.apache.kafka.connect.transforms.ValueToKey", + "transforms.sku_id_to_key.fields": "sku_id" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json new file mode 100644 index 0000000000..8f5ba96465 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json @@ -0,0 +1,36 @@ +{ + "config": { + "topics": "product_inventory", + "schema.context.name": "default", + "input.data.format": "JSON_SR", + "connector.class": "AzureCognitiveSearchSink", + "name": "ai_search_product_inventory_sink", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azure.search.service.name": "[AZURE_SEARCH_SERVICE_NAME]", + "azure.search.api.key": "[AZURE_SEARCH_API_KEY]", + "azure.search.client.id": "[ARM_CLIENT_ID]", + "azure.search.client.secret": "[ARM_CLIENT_SECRET]", + "azure.search.tenant.id": "[ARM_TENANT_ID]", + "azure.search.subscription.id": "[ARM_SUBSCRIPTION_ID]", + "azure.search.resourcegroup.name": "[AZURE_RESOURCE_GROUP]", + "index.name": "product_inventory", + "write.method": "Upload", + "delete.enabled": "true", + "key.mode": "KEY", + "max.batch.size": "25", + "max.retry.ms": "300000", + "max.poll.interval.ms": "300000", + "max.poll.records": "500", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "transforms": "sku_id_to_key", + "transforms.sku_id_to_key.type": "org.apache.kafka.connect.transforms.ValueToKey", + "transforms.sku_id_to_key.fields": "sku_id" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json new file mode 100644 index 0000000000..5ea3cffe94 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json @@ -0,0 +1,35 @@ +{ + "config": { + "connector.class": "AzureBlobSource", + "name": "azure_blob_departments_source_connector", + "topic.regex.list": "departments:.*", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azblob.account.name": "[AZURE_STORAGE_ACCOUNT_NAME]", + "azblob.account.key": "[AZURE_STORAGE_ACCOUNT_KEY]", + "azblob.container.name": "departments", + "azblob.retry.type": "EXPONENTIAL", + "input.data.format": "JSON", + "output.data.format": "JSON", + "topics.dir": "topics", + "directory.delim": "/", + "behavior.on.error": "FAIL", + "format.bytearray.separator": "\n", + "task.batch.size": "10", + "file.discovery.starting.timestamp": "0", + "azblob.poll.interval.ms": "60000", + "record.batch.max.size": "200", + "tasks.max": "1", + "value.converter.decimal.format": "BASE64", + "value.converter.replace.null.with.default": "true", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.schemas.enable": "false", + "errors.tolerance": "none", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "value.converter.ignore.default.for.nullables": "false", + "auto.restart.on.user.error": "true" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json new file mode 100644 index 0000000000..52ef7e784d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json @@ -0,0 +1,35 @@ +{ + "config": { + "connector.class": "AzureBlobSource", + "name": "azure_blob_product_pricing_source_connector", + "topic.regex.list": "product_pricing:.*", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azblob.account.name": "[AZURE_STORAGE_ACCOUNT_NAME]", + "azblob.account.key": "[AZURE_STORAGE_ACCOUNT_KEY]", + "azblob.container.name": "product-pricing", + "azblob.retry.type": "EXPONENTIAL", + "input.data.format": "JSON", + "output.data.format": "JSON", + "topics.dir": "topics", + "directory.delim": "/", + "behavior.on.error": "FAIL", + "format.bytearray.separator": "\n", + "task.batch.size": "10", + "file.discovery.starting.timestamp": "0", + "azblob.poll.interval.ms": "60000", + "record.batch.max.size": "200", + "tasks.max": "1", + "value.converter.decimal.format": "BASE64", + "value.converter.replace.null.with.default": "true", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.schemas.enable": "false", + "errors.tolerance": "none", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "value.converter.ignore.default.for.nullables": "false", + "auto.restart.on.user.error": "true" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json new file mode 100644 index 0000000000..703b8fb105 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json @@ -0,0 +1,35 @@ +{ + "config": { + "connector.class": "AzureBlobSource", + "name": "azure_blob_product_skus_source_connector", + "topic.regex.list": "product_skus:.*", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "azblob.account.name": "[AZURE_STORAGE_ACCOUNT_NAME]", + "azblob.account.key": "[AZURE_STORAGE_ACCOUNT_KEY]", + "azblob.container.name": "product-skus", + "azblob.retry.type": "EXPONENTIAL", + "input.data.format": "JSON", + "output.data.format": "JSON", + "topics.dir": "topics", + "directory.delim": "/", + "behavior.on.error": "FAIL", + "format.bytearray.separator": "\n", + "task.batch.size": "10", + "file.discovery.starting.timestamp": "0", + "azblob.poll.interval.ms": "60000", + "record.batch.max.size": "200", + "tasks.max": "1", + "value.converter.decimal.format": "BASE64", + "value.converter.replace.null.with.default": "true", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.schemas.enable": "false", + "errors.tolerance": "none", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy", + "value.converter.ignore.default.for.nullables": "false", + "auto.restart.on.user.error": "true" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json new file mode 100644 index 0000000000..9639e64ba2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_purchases_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "purchases#purchases", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json new file mode 100644 index 0000000000..a8dca07930 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_replenishments_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "replenishments#replenishments", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json new file mode 100644 index 0000000000..8552cc6999 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_returns_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "returns#returns", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md new file mode 100644 index 0000000000..a13df67658 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md @@ -0,0 +1,11 @@ +This folder contains seed data for the application + +We have data for the following collections: +- departments - this contains information about the departments available +- product_skus - all the unique SKUs available in the store +- product_pricing - the unit price for each sku +- purchases - transactions where customers purchased one or more items +- returns - transactions where customers returned one or more items +- replenishments - transactions where suppliers replinished one or more items +- product_inventory - the global inventory count for each SKU +- net_sales - the global view sales for a particular SKU considering returns as well \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md new file mode 100644 index 0000000000..c68abe83da --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md @@ -0,0 +1,19 @@ +### Uploading Blob Store Contents + +We can use the following steps to upload the blob store contents. First you will need to login to the Azure CLI. + +````bash + +az login + +```` + +#### Batch File Uploads + +We can upload the departments, product_pricing and product_skus dataset using the following Azure CLI commands: + +````bash + + + +```` \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh new file mode 100755 index 0000000000..58172a6c64 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh @@ -0,0 +1,38 @@ +#!/bin/bash + + +upload_to_blob_storage() { + + STORAGE_ACCOUNT_NAME="${AZURE_STORAGE_ACCOUNT_NAME}" + + TARGET_FOLDER=$1 + + DESTINATION_CONTAINER="${TARGET_FOLDER//_/-}" + + echo "Uploading Files from ${TARGET_FOLDER} to ${STORAGE_ACCOUNT_NAME} ..." + + echo "Changing directory to ${TARGET_FOLDER}" + cd ${TARGET_FOLDER} + + echo "Uploading JSON files to Azure Blob Storage Account ${STORAGE_ACCOUNT_NAME}/${DESTINATION_CONTAINER}/topics ..." + + az storage blob upload-batch \ + --account-name "${STORAGE_ACCOUNT_NAME}" \ + --account-key "${AZURE_STORAGE_ACCOUNT_KEY}" \ + --destination "${DESTINATION_CONTAINER}/topics" \ + --source . \ + --overwrite \ + --pattern "*.json" + + + echo "Upload completed." + + cd .. + +} + +upload_to_blob_storage "departments" +upload_to_blob_storage "product_pricing" +upload_to_blob_storage "product_skus" + +echo "All uploads completed." \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json new file mode 100644 index 0000000000..3faee78a40 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json @@ -0,0 +1,4 @@ +{ + "department": "appliance", + "description": "The appliance department is where we have simple use electronics for the home but mostly for the kitchen area. This is the only department were returned items can count towards the available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json new file mode 100644 index 0000000000..6afb38f0bd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json @@ -0,0 +1,4 @@ +{ + "department": "cleaning", + "description": "This is where we find cleaning supplies. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json new file mode 100644 index 0000000000..e76e02da7c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json @@ -0,0 +1,4 @@ +{ + "department": "dairy", + "description": "The dairy department where we find products like cheese, milk, butter and other dairy items. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json new file mode 100644 index 0000000000..916f559dde --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json @@ -0,0 +1,4 @@ +{ + "department": "deli", + "description": "This is where we find cooked food and other ready-to-eat meals. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json new file mode 100644 index 0000000000..8ae9dc22dc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json @@ -0,0 +1,4 @@ +{ + "department": "meat", + "description": "This is where we find meats such as chicken, pork, beef, lamb etc. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json new file mode 100644 index 0000000000..9cd81c200c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json @@ -0,0 +1,4 @@ +{ + "department": "pharmacy", + "description": "This is where we find pharmaceutical items like medications and first aid kits. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json new file mode 100644 index 0000000000..af785f89ca --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json @@ -0,0 +1,4 @@ +{ + "department": "produce", + "description": "The produce departments is where we find fresh fruits and vegatables. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema new file mode 100644 index 0000000000..357445f306 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Departments Key", + "description": "A unique identifier for the department", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema new file mode 100644 index 0000000000..2257ad8b2a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema @@ -0,0 +1,16 @@ +{ + "type": "object", + "title": "Departments Value", + "description": "Contains the department and description of the product SKU.", + "properties": { + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + }, + "description": { + "type": "string" + } + }, + "required": ["department", "description"], + "additionalProperties": false + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json new file mode 100644 index 0000000000..2a3f9097c2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json @@ -0,0 +1,4 @@ +{ + "department": "seafood", + "description": "This is the department where we find seafood products. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json new file mode 100644 index 0000000000..3faee78a40 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json @@ -0,0 +1,4 @@ +{ + "department": "appliance", + "description": "The appliance department is where we have simple use electronics for the home but mostly for the kitchen area. This is the only department were returned items can count towards the available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json new file mode 100644 index 0000000000..6afb38f0bd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json @@ -0,0 +1,4 @@ +{ + "department": "cleaning", + "description": "This is where we find cleaning supplies. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json new file mode 100644 index 0000000000..e76e02da7c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json @@ -0,0 +1,4 @@ +{ + "department": "dairy", + "description": "The dairy department where we find products like cheese, milk, butter and other dairy items. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json new file mode 100644 index 0000000000..916f559dde --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json @@ -0,0 +1,4 @@ +{ + "department": "deli", + "description": "This is where we find cooked food and other ready-to-eat meals. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json new file mode 100644 index 0000000000..8ae9dc22dc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json @@ -0,0 +1,4 @@ +{ + "department": "meat", + "description": "This is where we find meats such as chicken, pork, beef, lamb etc. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json new file mode 100644 index 0000000000..9cd81c200c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json @@ -0,0 +1,4 @@ +{ + "department": "pharmacy", + "description": "This is where we find pharmaceutical items like medications and first aid kits. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json new file mode 100644 index 0000000000..af785f89ca --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json @@ -0,0 +1,4 @@ +{ + "department": "produce", + "description": "The produce departments is where we find fresh fruits and vegatables. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema new file mode 100644 index 0000000000..357445f306 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Departments Key", + "description": "A unique identifier for the department", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema new file mode 100644 index 0000000000..2257ad8b2a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema @@ -0,0 +1,16 @@ +{ + "type": "object", + "title": "Departments Value", + "description": "Contains the department and description of the product SKU.", + "properties": { + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + }, + "description": { + "type": "string" + } + }, + "required": ["department", "description"], + "additionalProperties": false + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json new file mode 100644 index 0000000000..2a3f9097c2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json @@ -0,0 +1,4 @@ +{ + "department": "seafood", + "description": "This is the department where we find seafood products. Items returned from this department do not count towards available inventory numbers." +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json new file mode 100644 index 0000000000..4cbb93f670 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json @@ -0,0 +1,6 @@ +{ + "sku_id": "101", + "name": "Toaster", + "department": "appliance", + "net_sales": 450.97 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema new file mode 100644 index 0000000000..490cbf1bb7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Net Sales SKU identifier for the product", + "description": "A unique identifier for the product SKU pricing", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema new file mode 100644 index 0000000000..f3dfa1b45c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema @@ -0,0 +1,25 @@ +{ + "title": "Net Sales for the Product SKU", + "description": "Schema for a sales record containing SKU ID, product name, department, and cummulative net sales amount.", + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "description": "Unique identifier for the stock keeping unit (SKU)." + }, + "name": { + "type": "string", + "description": "Name of the Product" + }, + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + }, + "net_sales": { + "type": "number", + "description": "Net sales amount for the transaction." + } + }, + "required": ["sku_id", "name", "department", "net_sales"] + } + \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json new file mode 100644 index 0000000000..ccfa53e7d3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json @@ -0,0 +1,8 @@ +{ + "sku_id": "101", + "inventory_level": 300.00, + "unit_price": 9.99, + "name": "Toaster", + "description": "Electric Toaster", + "department":"appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json new file mode 100644 index 0000000000..5474eb9dc8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json @@ -0,0 +1,8 @@ +{ + "sku_id": "102", + "inventory_level": 55.00, + "unit_price": 29.95, + "name": "Microwave Oven", + "description": "A solar-powered Microwave oven", + "department":"appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema new file mode 100644 index 0000000000..8e10f3ed2e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Product inventory Title SKU identifier Key", + "description": "A unique identifier for the product inventory SKU", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema new file mode 100644 index 0000000000..fc4c00e6ce --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema @@ -0,0 +1,37 @@ +{ + "description": "This schema defines the structure of the product inventory data.", + "title": "Product inventory Title SKU identifier Value", + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "minLength": 1 + }, + "inventory_level": { + "type": "number" + }, + "unit_price": { + "type": "number" + }, + "name": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 1 + }, + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + } + }, + "required": [ + "sku_id", + "inventory_level", + "unit_price", + "name", + "description", + "department" + ] + } \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json new file mode 100644 index 0000000000..33c615ba4e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json @@ -0,0 +1,5 @@ +{ + "id": "101", + "sku_id": "101", + "unit_price": 49.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json new file mode 100644 index 0000000000..30779ecdcf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json @@ -0,0 +1,5 @@ +{ + "id": "102", + "sku_id": "102", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json new file mode 100644 index 0000000000..be1917d070 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json @@ -0,0 +1,5 @@ +{ + "id": "103", + "sku_id": "103", + "unit_price": 199.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json new file mode 100644 index 0000000000..18acecd534 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json @@ -0,0 +1,5 @@ +{ + "id": "104", + "sku_id": "104", + "unit_price": 89.95 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json new file mode 100644 index 0000000000..b2c67c434a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json @@ -0,0 +1,5 @@ +{ + "id": "105", + "sku_id": "105", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json new file mode 100644 index 0000000000..c87d60112f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json @@ -0,0 +1,5 @@ +{ + "id": "106", + "sku_id": "106", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json new file mode 100644 index 0000000000..00d2507b2c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json @@ -0,0 +1,5 @@ +{ + "id": "107", + "sku_id": "107", + "unit_price": 149.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json new file mode 100644 index 0000000000..fcf9b8332f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json @@ -0,0 +1,5 @@ +{ + "id": "108", + "sku_id": "108", + "unit_price": 59.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json new file mode 100644 index 0000000000..d44599296e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json @@ -0,0 +1,5 @@ +{ + "id": "109", + "sku_id": "109", + "unit_price": 99.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json new file mode 100644 index 0000000000..5c32e3c561 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json @@ -0,0 +1,5 @@ +{ + "id": "110", + "sku_id": "110", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json new file mode 100644 index 0000000000..1576bb08f6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json @@ -0,0 +1,5 @@ +{ + "id": "111", + "sku_id": "111", + "unit_price": 299.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json new file mode 100644 index 0000000000..ba2aedc68d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json @@ -0,0 +1,5 @@ +{ + "id": "112", + "sku_id": "112", + "unit_price": 45.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json new file mode 100644 index 0000000000..e6e76a4049 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json @@ -0,0 +1,5 @@ +{ + "id": "113", + "sku_id": "113", + "unit_price": 79.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json new file mode 100644 index 0000000000..4ef56bc85f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json @@ -0,0 +1,5 @@ +{ + "id": "114", + "sku_id": "114", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json new file mode 100644 index 0000000000..6e3de597ca --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json @@ -0,0 +1,5 @@ +{ + "id": "115", + "sku_id": "115", + "unit_price": 29.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json new file mode 100644 index 0000000000..bee9c3a07c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json @@ -0,0 +1,5 @@ +{ + "id": "116", + "sku_id": "116", + "unit_price": 129.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json new file mode 100644 index 0000000000..a0a00b5ae0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json @@ -0,0 +1,5 @@ +{ + "id": "117", + "sku_id": "117", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json new file mode 100644 index 0000000000..0ca7c8ec42 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json @@ -0,0 +1,5 @@ +{ + "id": "118", + "sku_id": "118", + "unit_price": 69.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json new file mode 100644 index 0000000000..33b5eb6017 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json @@ -0,0 +1,5 @@ +{ + "id": "119", + "sku_id": "119", + "unit_price": 99.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json new file mode 100644 index 0000000000..1bb5dd2386 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json @@ -0,0 +1,5 @@ +{ + "id": "120", + "sku_id": "120", + "unit_price": 399.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json new file mode 100644 index 0000000000..ca478fcaff --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json @@ -0,0 +1,5 @@ +{ + "id": "121", + "sku_id": "121", + "unit_price": 69.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json new file mode 100644 index 0000000000..08d24eeb1f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json @@ -0,0 +1,5 @@ +{ + "id": "122", + "sku_id": "122", + "unit_price": 129.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json new file mode 100644 index 0000000000..43cde5bd8a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json @@ -0,0 +1,5 @@ +{ + "id": "123", + "sku_id": "123", + "unit_price": 69.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json new file mode 100644 index 0000000000..24b7c2bddd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json @@ -0,0 +1,5 @@ +{ + "id": "124", + "sku_id": "124", + "unit_price": 89.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json new file mode 100644 index 0000000000..45735595d8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json @@ -0,0 +1,5 @@ +{ + "id": "125", + "sku_id": "125", + "unit_price": 25.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json new file mode 100644 index 0000000000..d2953ed114 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json @@ -0,0 +1,5 @@ +{ + "id": "201", + "sku_id": "201", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json new file mode 100644 index 0000000000..71b3fd279a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json @@ -0,0 +1,5 @@ +{ + "id": "202", + "sku_id": "202", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json new file mode 100644 index 0000000000..ba376831fb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json @@ -0,0 +1,5 @@ +{ + "id": "203", + "sku_id": "203", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json new file mode 100644 index 0000000000..43e0d37243 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json @@ -0,0 +1,5 @@ +{ + "id": "204", + "sku_id": "204", + "unit_price": 3.59 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json new file mode 100644 index 0000000000..b2f7d92a54 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json @@ -0,0 +1,5 @@ +{ + "id": "205", + "sku_id": "205", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json new file mode 100644 index 0000000000..af842a3a66 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json @@ -0,0 +1,5 @@ +{ + "id": "206", + "sku_id": "206", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json new file mode 100644 index 0000000000..d3f749b810 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json @@ -0,0 +1,5 @@ +{ + "id": "207", + "sku_id": "207", + "unit_price": 6.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json new file mode 100644 index 0000000000..f6fbe1b0e7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json @@ -0,0 +1,5 @@ +{ + "id": "208", + "sku_id": "208", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json new file mode 100644 index 0000000000..f4f0f95e2a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json @@ -0,0 +1,5 @@ +{ + "id": "209", + "sku_id": "209", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json new file mode 100644 index 0000000000..f11c1f1a7d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json @@ -0,0 +1,5 @@ +{ + "id": "210", + "sku_id": "210", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json new file mode 100644 index 0000000000..a82211674c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json @@ -0,0 +1,5 @@ +{ + "id": "211", + "sku_id": "211", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json new file mode 100644 index 0000000000..a9fd2a86cd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json @@ -0,0 +1,5 @@ +{ + "id": "212", + "sku_id": "212", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json new file mode 100644 index 0000000000..80e34507eb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json @@ -0,0 +1,5 @@ +{ + "id": "213", + "sku_id": "213", + "unit_price": 3.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json new file mode 100644 index 0000000000..b0ed15adf9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json @@ -0,0 +1,5 @@ +{ + "id": "214", + "sku_id": "214", + "unit_price": 4.19 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json new file mode 100644 index 0000000000..7e6e5c8806 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json @@ -0,0 +1,5 @@ +{ + "id": "215", + "sku_id": "215", + "unit_price": 2.79 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json new file mode 100644 index 0000000000..7b8c24c59e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json @@ -0,0 +1,5 @@ +{ + "id": "216", + "sku_id": "216", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json new file mode 100644 index 0000000000..3336675d60 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json @@ -0,0 +1,5 @@ +{ + "id": "217", + "sku_id": "217", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json new file mode 100644 index 0000000000..1ada5b3479 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json @@ -0,0 +1,5 @@ +{ + "id": "218", + "sku_id": "218", + "unit_price": 7.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json new file mode 100644 index 0000000000..b87d9a162f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json @@ -0,0 +1,5 @@ +{ + "id": "219", + "sku_id": "219", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json new file mode 100644 index 0000000000..7d9275eac3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json @@ -0,0 +1,5 @@ +{ + "id": "220", + "sku_id": "220", + "unit_price": 12.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json new file mode 100644 index 0000000000..b80db7a92a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json @@ -0,0 +1,5 @@ +{ + "id": "221", + "sku_id": "221", + "unit_price": 1.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json new file mode 100644 index 0000000000..0688042174 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json @@ -0,0 +1,5 @@ +{ + "id": "222", + "sku_id": "222", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json new file mode 100644 index 0000000000..0ae1cad58e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json @@ -0,0 +1,5 @@ +{ + "id": "223", + "sku_id": "223", + "unit_price": 7.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json new file mode 100644 index 0000000000..3b5381dc1d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json @@ -0,0 +1,5 @@ +{ + "id": "224", + "sku_id": "224", + "unit_price": 4.79 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json new file mode 100644 index 0000000000..f1c5221f68 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json @@ -0,0 +1,5 @@ +{ + "id": "225", + "sku_id": "225", + "unit_price": 8.39 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json new file mode 100644 index 0000000000..43bc08d8d0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json @@ -0,0 +1,5 @@ +{ + "id": "301", + "sku_id": "301", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json new file mode 100644 index 0000000000..814663df24 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json @@ -0,0 +1,5 @@ +{ + "id": "302", + "sku_id": "302", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json new file mode 100644 index 0000000000..41fc0dd2cf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json @@ -0,0 +1,5 @@ +{ + "id": "303", + "sku_id": "303", + "unit_price": 2.89 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json new file mode 100644 index 0000000000..3a4d47e169 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json @@ -0,0 +1,5 @@ +{ + "id": "304", + "sku_id": "304", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json new file mode 100644 index 0000000000..0da44bbaf9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json @@ -0,0 +1,5 @@ +{ + "id": "305", + "sku_id": "305", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json new file mode 100644 index 0000000000..f997e5764b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json @@ -0,0 +1,5 @@ +{ + "id": "306", + "sku_id": "306", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json new file mode 100644 index 0000000000..ecf16d46db --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json @@ -0,0 +1,5 @@ +{ + "id": "307", + "sku_id": "307", + "unit_price": 4.19 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json new file mode 100644 index 0000000000..d47a62ca87 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json @@ -0,0 +1,5 @@ +{ + "id": "308", + "sku_id": "308", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json new file mode 100644 index 0000000000..0860aa1e7f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json @@ -0,0 +1,5 @@ +{ + "id": "309", + "sku_id": "309", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json new file mode 100644 index 0000000000..51600df563 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json @@ -0,0 +1,5 @@ +{ + "id": "310", + "sku_id": "310", + "unit_price": 3.79 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json new file mode 100644 index 0000000000..d6015e1486 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json @@ -0,0 +1,5 @@ +{ + "id": "311", + "sku_id": "311", + "unit_price": 2.59 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json new file mode 100644 index 0000000000..58450e4ab8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json @@ -0,0 +1,5 @@ +{ + "id": "312", + "sku_id": "312", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json new file mode 100644 index 0000000000..002104c402 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json @@ -0,0 +1,5 @@ +{ + "id": "313", + "sku_id": "313", + "unit_price": 3.89 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json new file mode 100644 index 0000000000..cac5276317 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json @@ -0,0 +1,5 @@ +{ + "id": "314", + "sku_id": "314", + "unit_price": 5.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json new file mode 100644 index 0000000000..17e6a83a94 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json @@ -0,0 +1,5 @@ +{ + "id": "315", + "sku_id": "315", + "unit_price": 4.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json new file mode 100644 index 0000000000..8e82a96d18 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json @@ -0,0 +1,5 @@ +{ + "id": "316", + "sku_id": "316", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json new file mode 100644 index 0000000000..00225e7213 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json @@ -0,0 +1,5 @@ +{ + "id": "317", + "sku_id": "317", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json new file mode 100644 index 0000000000..3efe300b93 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json @@ -0,0 +1,5 @@ +{ + "id": "318", + "sku_id": "318", + "unit_price": 1.89 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json new file mode 100644 index 0000000000..6cdf8e227c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json @@ -0,0 +1,5 @@ +{ + "id": "319", + "sku_id": "319", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json new file mode 100644 index 0000000000..2758b1a9c6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json @@ -0,0 +1,5 @@ +{ + "id": "320", + "sku_id": "320", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json new file mode 100644 index 0000000000..bcafd68146 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json @@ -0,0 +1,5 @@ +{ + "id": "321", + "sku_id": "321", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json new file mode 100644 index 0000000000..03a608e853 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json @@ -0,0 +1,5 @@ +{ + "id": "322", + "sku_id": "322", + "unit_price": 3.59 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json new file mode 100644 index 0000000000..d232ea9b4c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json @@ -0,0 +1,5 @@ +{ + "id": "323", + "sku_id": "323", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json new file mode 100644 index 0000000000..6cfeb09e6a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json @@ -0,0 +1,5 @@ +{ + "id": "324", + "sku_id": "324", + "unit_price": 3.79 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json new file mode 100644 index 0000000000..ecf8ebbb97 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json @@ -0,0 +1,5 @@ +{ + "id": "325", + "sku_id": "325", + "unit_price": 3.19 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json new file mode 100644 index 0000000000..5d61d7ff8c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json @@ -0,0 +1,5 @@ +{ + "id": "401", + "sku_id": "401", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json new file mode 100644 index 0000000000..0bcb6afcd0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json @@ -0,0 +1,5 @@ +{ + "id": "402", + "sku_id": "402", + "unit_price": 9.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json new file mode 100644 index 0000000000..b2e81611ab --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json @@ -0,0 +1,5 @@ +{ + "id": "403", + "sku_id": "403", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json new file mode 100644 index 0000000000..5153483da1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json @@ -0,0 +1,5 @@ +{ + "id": "404", + "sku_id": "404", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json new file mode 100644 index 0000000000..516829764c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json @@ -0,0 +1,5 @@ +{ + "id": "405", + "sku_id": "405", + "unit_price": 10.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json new file mode 100644 index 0000000000..5cef1170f2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json @@ -0,0 +1,5 @@ +{ + "id": "406", + "sku_id": "406", + "unit_price": 7.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json new file mode 100644 index 0000000000..65a8b836c2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json @@ -0,0 +1,5 @@ +{ + "id": "407", + "sku_id": "407", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json new file mode 100644 index 0000000000..27efa3c2c3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json @@ -0,0 +1,5 @@ +{ + "id": "408", + "sku_id": "408", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json new file mode 100644 index 0000000000..78fc969dc7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json @@ -0,0 +1,5 @@ +{ + "id": "409", + "sku_id": "409", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json new file mode 100644 index 0000000000..accce4f24d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json @@ -0,0 +1,5 @@ +{ + "id": "410", + "sku_id": "410", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json new file mode 100644 index 0000000000..57d19e5159 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json @@ -0,0 +1,5 @@ +{ + "id": "411", + "sku_id": "411", + "unit_price": 6.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json new file mode 100644 index 0000000000..6f9dd102e7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json @@ -0,0 +1,5 @@ +{ + "id": "412", + "sku_id": "412", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json new file mode 100644 index 0000000000..626c62111a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json @@ -0,0 +1,5 @@ +{ + "id": "413", + "sku_id": "413", + "unit_price": 7.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json new file mode 100644 index 0000000000..b612f2c5a7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json @@ -0,0 +1,5 @@ +{ + "id": "414", + "sku_id": "414", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json new file mode 100644 index 0000000000..843854b138 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json @@ -0,0 +1,5 @@ +{ + "id": "415", + "sku_id": "415", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json new file mode 100644 index 0000000000..408c3d7a7c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json @@ -0,0 +1,5 @@ +{ + "id": "416", + "sku_id": "416", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json new file mode 100644 index 0000000000..59077d5ebe --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json @@ -0,0 +1,5 @@ +{ + "id": "417", + "sku_id": "417", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json new file mode 100644 index 0000000000..77c59f0475 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json @@ -0,0 +1,5 @@ +{ + "id": "418", + "sku_id": "418", + "unit_price": 7.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json new file mode 100644 index 0000000000..425f2c318a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json @@ -0,0 +1,5 @@ +{ + "id": "419", + "sku_id": "419", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json new file mode 100644 index 0000000000..b747386990 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json @@ -0,0 +1,5 @@ +{ + "id": "420", + "sku_id": "420", + "unit_price": 10.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json new file mode 100644 index 0000000000..d9830afa29 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json @@ -0,0 +1,5 @@ +{ + "id": "421", + "sku_id": "421", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json new file mode 100644 index 0000000000..1413e11e5a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json @@ -0,0 +1,5 @@ +{ + "id": "422", + "sku_id": "422", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json new file mode 100644 index 0000000000..8b422baf2c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json @@ -0,0 +1,5 @@ +{ + "id": "423", + "sku_id": "423", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json new file mode 100644 index 0000000000..5700c4211e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json @@ -0,0 +1,5 @@ +{ + "id": "424", + "sku_id": "424", + "unit_price": 4.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json new file mode 100644 index 0000000000..8e62840b46 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json @@ -0,0 +1,5 @@ +{ + "id": "425", + "sku_id": "425", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json new file mode 100644 index 0000000000..98f0f80feb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json @@ -0,0 +1,5 @@ +{ + "id": "501", + "sku_id": "501", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json new file mode 100644 index 0000000000..7a2bbcae27 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json @@ -0,0 +1,5 @@ +{ + "id": "502", + "sku_id": "502", + "unit_price": 9.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json new file mode 100644 index 0000000000..8445cc59ca --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json @@ -0,0 +1,5 @@ +{ + "id": "503", + "sku_id": "503", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json new file mode 100644 index 0000000000..f77b59f773 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json @@ -0,0 +1,5 @@ +{ + "id": "504", + "sku_id": "504", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json new file mode 100644 index 0000000000..57153a383b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json @@ -0,0 +1,5 @@ +{ + "id": "505", + "sku_id": "505", + "unit_price": 7.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json new file mode 100644 index 0000000000..66c0b172ba --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json @@ -0,0 +1,5 @@ +{ + "id": "506", + "sku_id": "506", + "unit_price": 18.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json new file mode 100644 index 0000000000..543724baf3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json @@ -0,0 +1,5 @@ +{ + "id": "507", + "sku_id": "507", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json new file mode 100644 index 0000000000..0b7a81d15b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json @@ -0,0 +1,5 @@ +{ + "id": "508", + "sku_id": "508", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json new file mode 100644 index 0000000000..415657d43a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json @@ -0,0 +1,5 @@ +{ + "id": "509", + "sku_id": "509", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json new file mode 100644 index 0000000000..69a1fb9d44 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json @@ -0,0 +1,5 @@ +{ + "id": "510", + "sku_id": "510", + "unit_price": 16.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json new file mode 100644 index 0000000000..9c7593196e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json @@ -0,0 +1,5 @@ +{ + "id": "511", + "sku_id": "511", + "unit_price": 5.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json new file mode 100644 index 0000000000..719029874d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json @@ -0,0 +1,5 @@ +{ + "id": "512", + "sku_id": "512", + "unit_price": 12.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json new file mode 100644 index 0000000000..0c8e9e7d05 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json @@ -0,0 +1,5 @@ +{ + "id": "513", + "sku_id": "513", + "unit_price": 20.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json new file mode 100644 index 0000000000..8dcf5a6197 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json @@ -0,0 +1,5 @@ +{ + "id": "514", + "sku_id": "514", + "unit_price": 12.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json new file mode 100644 index 0000000000..6bc6eb5074 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json @@ -0,0 +1,5 @@ +{ + "id": "515", + "sku_id": "515", + "unit_price": 8.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json new file mode 100644 index 0000000000..47d9590c9e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json @@ -0,0 +1,5 @@ +{ + "id": "516", + "sku_id": "516", + "unit_price": 10.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json new file mode 100644 index 0000000000..ebcecfdb33 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json @@ -0,0 +1,5 @@ +{ + "id": "517", + "sku_id": "517", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json new file mode 100644 index 0000000000..5be88115db --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json @@ -0,0 +1,5 @@ +{ + "id": "518", + "sku_id": "518", + "unit_price": 7.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json new file mode 100644 index 0000000000..07df0576fa --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json @@ -0,0 +1,5 @@ +{ + "id": "519", + "sku_id": "519", + "unit_price": 21.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json new file mode 100644 index 0000000000..2603f890c0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json @@ -0,0 +1,5 @@ +{ + "id": "520", + "sku_id": "520", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json new file mode 100644 index 0000000000..c376ea152a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json @@ -0,0 +1,5 @@ +{ + "id": "521", + "sku_id": "521", + "unit_price": 11.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json new file mode 100644 index 0000000000..3721eb86bf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json @@ -0,0 +1,5 @@ +{ + "id": "522", + "sku_id": "522", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json new file mode 100644 index 0000000000..dad8800375 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json @@ -0,0 +1,5 @@ +{ + "id": "523", + "sku_id": "523", + "unit_price": 6.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json new file mode 100644 index 0000000000..f10b3aad89 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json @@ -0,0 +1,5 @@ +{ + "id": "524", + "sku_id": "524", + "unit_price": 15.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json new file mode 100644 index 0000000000..a5dce3e37b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json @@ -0,0 +1,5 @@ +{ + "id": "525", + "sku_id": "525", + "unit_price": 13.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json new file mode 100644 index 0000000000..f56271e3f2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json @@ -0,0 +1,5 @@ +{ + "id": "601", + "sku_id": "601", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json new file mode 100644 index 0000000000..5ca8dd1492 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json @@ -0,0 +1,5 @@ +{ + "id": "602", + "sku_id": "602", + "unit_price": 12.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json new file mode 100644 index 0000000000..ee8fa64988 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json @@ -0,0 +1,5 @@ +{ + "id": "603", + "sku_id": "603", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json new file mode 100644 index 0000000000..0d69ae3bd9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json @@ -0,0 +1,5 @@ +{ + "id": "604", + "sku_id": "604", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json new file mode 100644 index 0000000000..4de4afeafa --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json @@ -0,0 +1,5 @@ +{ + "id": "605", + "sku_id": "605", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json new file mode 100644 index 0000000000..6626c625a7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json @@ -0,0 +1,5 @@ +{ + "id": "606", + "sku_id": "606", + "unit_price": 24.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json new file mode 100644 index 0000000000..ac6e29afd7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json @@ -0,0 +1,5 @@ +{ + "id": "607", + "sku_id": "607", + "unit_price": 39.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json new file mode 100644 index 0000000000..4d5974b888 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json @@ -0,0 +1,5 @@ +{ + "id": "608", + "sku_id": "608", + "unit_price": 15.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json new file mode 100644 index 0000000000..77a73a3934 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json @@ -0,0 +1,5 @@ +{ + "id": "609", + "sku_id": "609", + "unit_price": 22.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json new file mode 100644 index 0000000000..7d7837c818 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json @@ -0,0 +1,5 @@ +{ + "id": "610", + "sku_id": "610", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json new file mode 100644 index 0000000000..dad76f62ec --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json @@ -0,0 +1,5 @@ +{ + "id": "611", + "sku_id": "611", + "unit_price": 21.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json new file mode 100644 index 0000000000..e9cb8b570f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json @@ -0,0 +1,5 @@ +{ + "id": "612", + "sku_id": "612", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json new file mode 100644 index 0000000000..878396fc55 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json @@ -0,0 +1,5 @@ +{ + "id": "613", + "sku_id": "613", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json new file mode 100644 index 0000000000..d5f6b4c52a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json @@ -0,0 +1,5 @@ +{ + "id": "614", + "sku_id": "614", + "unit_price": 27.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json new file mode 100644 index 0000000000..72cb0df0ca --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json @@ -0,0 +1,5 @@ +{ + "id": "615", + "sku_id": "615", + "unit_price": 6.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json new file mode 100644 index 0000000000..e4a0be17d7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json @@ -0,0 +1,5 @@ +{ + "id": "616", + "sku_id": "616", + "unit_price": 10.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json new file mode 100644 index 0000000000..41e6574ea1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json @@ -0,0 +1,5 @@ +{ + "id": "617", + "sku_id": "617", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json new file mode 100644 index 0000000000..0bbfa87d4b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json @@ -0,0 +1,5 @@ +{ + "id": "618", + "sku_id": "618", + "unit_price": 9.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json new file mode 100644 index 0000000000..c0650619d7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json @@ -0,0 +1,5 @@ +{ + "id": "619", + "sku_id": "619", + "unit_price": 13.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json new file mode 100644 index 0000000000..807a04661e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json @@ -0,0 +1,5 @@ +{ + "id": "620", + "sku_id": "620", + "unit_price": 18.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json new file mode 100644 index 0000000000..6d43ac731a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json @@ -0,0 +1,5 @@ +{ + "id": "621", + "sku_id": "621", + "unit_price": 17.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json new file mode 100644 index 0000000000..48f538cdea --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json @@ -0,0 +1,5 @@ +{ + "id": "622", + "sku_id": "622", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json new file mode 100644 index 0000000000..ffd51b0336 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json @@ -0,0 +1,5 @@ +{ + "id": "623", + "sku_id": "623", + "unit_price": 15.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json new file mode 100644 index 0000000000..0030a18913 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json @@ -0,0 +1,5 @@ +{ + "id": "624", + "sku_id": "624", + "unit_price": 11.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json new file mode 100644 index 0000000000..58875cab8b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json @@ -0,0 +1,5 @@ +{ + "id": "625", + "sku_id": "625", + "unit_price": 23.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json new file mode 100644 index 0000000000..455468f4d9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json @@ -0,0 +1,5 @@ +{ + "id": "701", + "sku_id": "701", + "unit_price": 1.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json new file mode 100644 index 0000000000..e943b2f754 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json @@ -0,0 +1,5 @@ +{ + "id": "702", + "sku_id": "702", + "unit_price": 0.59 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json new file mode 100644 index 0000000000..e10054b138 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json @@ -0,0 +1,5 @@ +{ + "id": "703", + "sku_id": "703", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json new file mode 100644 index 0000000000..28daa10535 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json @@ -0,0 +1,5 @@ +{ + "id": "704", + "sku_id": "704", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json new file mode 100644 index 0000000000..065881a74d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json @@ -0,0 +1,5 @@ +{ + "id": "705", + "sku_id": "705", + "unit_price": 0.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json new file mode 100644 index 0000000000..9598f2e700 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json @@ -0,0 +1,5 @@ +{ + "id": "706", + "sku_id": "706", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json new file mode 100644 index 0000000000..6259e5f3c5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json @@ -0,0 +1,5 @@ +{ + "id": "707", + "sku_id": "707", + "unit_price": 1.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json new file mode 100644 index 0000000000..033e269b84 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json @@ -0,0 +1,5 @@ +{ + "id": "708", + "sku_id": "708", + "unit_price": 1.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json new file mode 100644 index 0000000000..4b6a876ef5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json @@ -0,0 +1,5 @@ +{ + "id": "709", + "sku_id": "709", + "unit_price": 0.79 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json new file mode 100644 index 0000000000..4daec77081 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json @@ -0,0 +1,5 @@ +{ + "id": "710", + "sku_id": "710", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json new file mode 100644 index 0000000000..665d89c0ed --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json @@ -0,0 +1,5 @@ +{ + "id": "711", + "sku_id": "711", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json new file mode 100644 index 0000000000..c7c2ad208a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json @@ -0,0 +1,5 @@ +{ + "id": "712", + "sku_id": "712", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json new file mode 100644 index 0000000000..509ff22685 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json @@ -0,0 +1,5 @@ +{ + "id": "713", + "sku_id": "713", + "unit_price": 0.89 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json new file mode 100644 index 0000000000..776438fe94 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json @@ -0,0 +1,5 @@ +{ + "id": "714", + "sku_id": "714", + "unit_price": 1.79 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json new file mode 100644 index 0000000000..15b4616e79 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json @@ -0,0 +1,5 @@ +{ + "id": "715", + "sku_id": "715", + "unit_price": 2.29 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json new file mode 100644 index 0000000000..4cae6c730c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json @@ -0,0 +1,5 @@ +{ + "id": "716", + "sku_id": "716", + "unit_price": 1.89 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json new file mode 100644 index 0000000000..95a5a1f7ff --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json @@ -0,0 +1,5 @@ +{ + "id": "717", + "sku_id": "717", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json new file mode 100644 index 0000000000..a35b17facb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json @@ -0,0 +1,5 @@ +{ + "id": "718", + "sku_id": "718", + "unit_price": 1.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json new file mode 100644 index 0000000000..5d24450fd9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json @@ -0,0 +1,5 @@ +{ + "id": "719", + "sku_id": "719", + "unit_price": 2.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json new file mode 100644 index 0000000000..f457faa5f9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json @@ -0,0 +1,5 @@ +{ + "id": "720", + "sku_id": "720", + "unit_price": 0.59 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json new file mode 100644 index 0000000000..a3d385a1c1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json @@ -0,0 +1,5 @@ +{ + "id": "721", + "sku_id": "721", + "unit_price": 0.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json new file mode 100644 index 0000000000..5da5ee7f53 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json @@ -0,0 +1,5 @@ +{ + "id": "722", + "sku_id": "722", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json new file mode 100644 index 0000000000..4543b17754 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json @@ -0,0 +1,5 @@ +{ + "id": "723", + "sku_id": "723", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json new file mode 100644 index 0000000000..1ea8749244 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json @@ -0,0 +1,5 @@ +{ + "id": "724", + "sku_id": "724", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json new file mode 100644 index 0000000000..6bea27553e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json @@ -0,0 +1,5 @@ +{ + "id": "725", + "sku_id": "725", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json new file mode 100644 index 0000000000..99efe1aca8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json @@ -0,0 +1,5 @@ +{ + "id": "801", + "sku_id": "801", + "unit_price": 14.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json new file mode 100644 index 0000000000..2f6440e5e8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json @@ -0,0 +1,5 @@ +{ + "id": "802", + "sku_id": "802", + "unit_price": 9.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json new file mode 100644 index 0000000000..7756bf5061 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json @@ -0,0 +1,5 @@ +{ + "id": "803", + "sku_id": "803", + "unit_price": 12.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json new file mode 100644 index 0000000000..333c87322a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json @@ -0,0 +1,5 @@ +{ + "id": "804", + "sku_id": "804", + "unit_price": 19.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json new file mode 100644 index 0000000000..da16d8ef12 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json @@ -0,0 +1,5 @@ +{ + "id": "805", + "sku_id": "805", + "unit_price": 25.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json new file mode 100644 index 0000000000..7681a8f8cd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json @@ -0,0 +1,5 @@ +{ + "id": "806", + "sku_id": "806", + "unit_price": 17.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json new file mode 100644 index 0000000000..f29d844f76 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json @@ -0,0 +1,5 @@ +{ + "id": "807", + "sku_id": "807", + "unit_price": 8.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json new file mode 100644 index 0000000000..3b15c7c132 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json @@ -0,0 +1,5 @@ +{ + "id": "808", + "sku_id": "808", + "unit_price": 29.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json new file mode 100644 index 0000000000..4f4e116282 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json @@ -0,0 +1,5 @@ +{ + "id": "809", + "sku_id": "809", + "unit_price": 11.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json new file mode 100644 index 0000000000..fa7d414350 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json @@ -0,0 +1,5 @@ +{ + "id": "810", + "sku_id": "810", + "unit_price": 16.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json new file mode 100644 index 0000000000..47271c87bb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json @@ -0,0 +1,5 @@ +{ + "id": "811", + "sku_id": "811", + "unit_price": 22.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json new file mode 100644 index 0000000000..55ca3e56db --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json @@ -0,0 +1,5 @@ +{ + "id": "812", + "sku_id": "812", + "unit_price": 10.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json new file mode 100644 index 0000000000..944fb22c8f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json @@ -0,0 +1,5 @@ +{ + "id": "813", + "sku_id": "813", + "unit_price": 26.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json new file mode 100644 index 0000000000..9bae40e662 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json @@ -0,0 +1,5 @@ +{ + "id": "814", + "sku_id": "814", + "unit_price": 2.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json new file mode 100644 index 0000000000..d7017e4bce --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json @@ -0,0 +1,5 @@ +{ + "id": "815", + "sku_id": "815", + "unit_price": 18.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json new file mode 100644 index 0000000000..f6d0445d38 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json @@ -0,0 +1,5 @@ +{ + "id": "816", + "sku_id": "816", + "unit_price": 4.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json new file mode 100644 index 0000000000..a1d54456a4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json @@ -0,0 +1,5 @@ +{ + "id": "817", + "sku_id": "817", + "unit_price": 1.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json new file mode 100644 index 0000000000..9d62b549a2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json @@ -0,0 +1,5 @@ +{ + "id": "818", + "sku_id": "818", + "unit_price": 3.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json new file mode 100644 index 0000000000..9e9aea87c7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json @@ -0,0 +1,5 @@ +{ + "id": "819", + "sku_id": "819", + "unit_price": 49.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json new file mode 100644 index 0000000000..3446e4fac7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json @@ -0,0 +1,5 @@ +{ + "id": "820", + "sku_id": "820", + "unit_price": 24.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json new file mode 100644 index 0000000000..12026da2ab --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json @@ -0,0 +1,5 @@ +{ + "id": "821", + "sku_id": "821", + "unit_price": 8.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json new file mode 100644 index 0000000000..91b8f0e649 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json @@ -0,0 +1,5 @@ +{ + "id": "822", + "sku_id": "822", + "unit_price": 12.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json new file mode 100644 index 0000000000..08202e2b5c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json @@ -0,0 +1,5 @@ +{ + "id": "823", + "sku_id": "823", + "unit_price": 15.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json new file mode 100644 index 0000000000..5f596b2fa5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json @@ -0,0 +1,5 @@ +{ + "id": "824", + "sku_id": "824", + "unit_price": 3.49 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json new file mode 100644 index 0000000000..739dd19379 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json @@ -0,0 +1,5 @@ +{ + "id": "825", + "sku_id": "825", + "unit_price": 5.99 +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema new file mode 100644 index 0000000000..7e8cbeb4f1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema @@ -0,0 +1,7 @@ +{ + "type": "string", + "title": "Product Pricing SKU Key", + "description": "A unique identifier for the product SKU pricing", + "pattern": "^[0-9]+$" +} + \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema new file mode 100644 index 0000000000..89f769ab79 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema @@ -0,0 +1,19 @@ +{ + "type": "object", + "description": "A unique identifier for the department in the retail store.", + "title": "Product Pricing Value", + "properties": { + "id": { + "type": "string" + }, + "sku_id": { + "type": "string" + }, + "unit_price": { + "type": "number" + } + }, + "required": ["id", "sku_id", "unit_price"], + "additionalProperties": false + } + \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json new file mode 100644 index 0000000000..b03381f704 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json @@ -0,0 +1,7 @@ +{ + "id": "101", + "sku_id": "101", + "name": "Smart Toaster", + "description": "A smart toaster with touchscreen controls and multiple toast settings for perfect browning every time.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json new file mode 100644 index 0000000000..654842e01f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json @@ -0,0 +1,7 @@ +{ + "id": "102", + "sku_id": "102", + "name": "Air Fryer Pro", + "description": "Healthy air fryer that cooks crispy meals with little to no oil. 3.7 qt capacity.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json new file mode 100644 index 0000000000..eca1d2da1f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json @@ -0,0 +1,7 @@ +{ + "id": "103", + "sku_id": "103", + "name": "Cordless Vacuum Cleaner", + "description": "Lightweight and powerful cordless vacuum cleaner with HEPA filtration for allergy relief.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json new file mode 100644 index 0000000000..47d8c64595 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json @@ -0,0 +1,7 @@ +{ + "id": "104", + "sku_id": "104", + "name": "Instant Pot Duo 7-in-1", + "description": "Multi-use electric pressure cooker that can be used as a slow cooker, rice cooker, steamer, and more.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json new file mode 100644 index 0000000000..c8e071ef63 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json @@ -0,0 +1,7 @@ +{ + "id": "105", + "sku_id": "105", + "name": "Electric Kettle", + "description": "1.7-liter electric kettle with auto shut-off and boil-dry protection for safe, fast boiling.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json new file mode 100644 index 0000000000..a28ff1de96 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json @@ -0,0 +1,7 @@ +{ + "id": "106", + "sku_id": "106", + "name": "7-Quart Slow Cooker", + "description": "Programmable slow cooker with a locking lid and digital controls for easy meal prep.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json new file mode 100644 index 0000000000..614af11691 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json @@ -0,0 +1,7 @@ +{ + "id": "107", + "sku_id": "107", + "name": "Food Processor", + "description": "Versatile food processor with a 14-cup capacity and various blades for chopping, slicing, and shredding.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json new file mode 100644 index 0000000000..d5f6ba4afb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json @@ -0,0 +1,7 @@ +{ + "id": "108", + "sku_id": "108", + "name": "Coffee Maker", + "description": "12-cup programmable coffee maker with brew strength settings and a pause-and-serve feature.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json new file mode 100644 index 0000000000..b450d0c925 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json @@ -0,0 +1,7 @@ +{ + "id": "109", + "sku_id": "109", + "name": "Soda Maker", + "description": "Transform plain water into sparkling drinks at home with this easy-to-use soda maker.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json new file mode 100644 index 0000000000..fa24903aba --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json @@ -0,0 +1,7 @@ +{ + "id": "110", + "sku_id": "110", + "name": "Electric Griddle", + "description": "Large non-stick electric griddle with adjustable temperature settings for pancakes, eggs, and more.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json new file mode 100644 index 0000000000..e8847d51a5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json @@ -0,0 +1,7 @@ +{ + "id": "111", + "sku_id": "111", + "name": "Stand Mixer", + "description": "Powerful stand mixer with multiple attachments for baking, whipping, and kneading dough.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json new file mode 100644 index 0000000000..42e4311eef --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json @@ -0,0 +1,7 @@ +{ + "id": "112", + "sku_id": "112", + "name": "Rice Cooker", + "description": "Automatic rice cooker with a keep-warm function and non-stick pot for easy cleaning.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json new file mode 100644 index 0000000000..a5e2a3fd13 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json @@ -0,0 +1,7 @@ +{ + "id": "113", + "sku_id": "113", + "name": "Induction Cooktop", + "description": "Portable induction cooktop with two burners for fast cooking and precise temperature control.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json new file mode 100644 index 0000000000..c405d5906b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json @@ -0,0 +1,7 @@ +{ + "id": "114", + "sku_id": "114", + "name": "Blender", + "description": "High-speed blender that crushes ice and blends fruits smoothly for your favorite smoothies.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json new file mode 100644 index 0000000000..79b35c6991 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json @@ -0,0 +1,7 @@ +{ + "id": "115", + "sku_id": "115", + "name": "Waffle Maker", + "description": "Non-stick waffle maker with adjustable browning control for golden, fluffy waffles.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json new file mode 100644 index 0000000000..80a1675ef2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json @@ -0,0 +1,7 @@ +{ + "id": "116", + "sku_id": "116", + "name": "Juicer", + "description": "Centrifugal juicer that extracts juice from fruits and veggies quickly and efficiently.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json new file mode 100644 index 0000000000..96aae93b4d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json @@ -0,0 +1,7 @@ +{ + "id": "117", + "sku_id": "117", + "name": "Microwave Oven", + "description": "Compact microwave oven with preset cooking options and a sleek design for any kitchen.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json new file mode 100644 index 0000000000..07a6c9fd8b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json @@ -0,0 +1,7 @@ +{ + "id": "118", + "sku_id": "118", + "name": "Electric Grill", + "description": "Indoor electric grill with non-stick surface and adjustable temperature for grilling year-round.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json new file mode 100644 index 0000000000..c98e509572 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json @@ -0,0 +1,7 @@ +{ + "id": "119", + "sku_id": "119", + "name": "Sous Vide Precision Cooker", + "description": "Sous vide cooker for perfectly cooked meals with a precision temperature control.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json new file mode 100644 index 0000000000..fbe2f66dda --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json @@ -0,0 +1,7 @@ +{ + "id": "120", + "sku_id": "120", + "name": "Dishwasher", + "description": "Compact countertop dishwasher with 6 washing programs for easy cleaning of dishes.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json new file mode 100644 index 0000000000..9c1949d6c8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json @@ -0,0 +1,7 @@ +{ + "id": "121", + "sku_id": "121", + "name": "Dehydrator", + "description": "Food dehydrator for drying fruits, vegetables, and jerky with temperature control settings.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json new file mode 100644 index 0000000000..f5c67a2177 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json @@ -0,0 +1,7 @@ +{ + "id": "122", + "sku_id": "122", + "name": "Portable Ice Maker", + "description": "Compact ice maker that produces bullet ice cubes in just 6 minutes, perfect for parties.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json new file mode 100644 index 0000000000..1a2130d62b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json @@ -0,0 +1,7 @@ +{ + "id": "123", + "sku_id": "123", + "name": "Electric Pressure Cooker", + "description": "Electric pressure cooker with easy-to-use controls for fast cooking of stews, soups, and more.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json new file mode 100644 index 0000000000..3fc2002db2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json @@ -0,0 +1,7 @@ +{ + "id": "124", + "sku_id": "124", + "name": "Bread Machine", + "description": "Automatic bread machine with multiple settings to bake fresh bread at home with ease.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json new file mode 100644 index 0000000000..d2efde5ac6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json @@ -0,0 +1,7 @@ +{ + "id": "125", + "sku_id": "125", + "name": "Kitchen Scale", + "description": "Digital kitchen scale with a large display and tare function for precise ingredient measurements.", + "department": "appliance" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json new file mode 100644 index 0000000000..e6a3ea5635 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json @@ -0,0 +1,7 @@ +{ + "id": "201", + "sku_id": "201", + "name": "All-Purpose Cleaner", + "description": "A versatile cleaner suitable for various surfaces, including countertops and floors. Provides sparkling results with a fresh lemon scent.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json new file mode 100644 index 0000000000..0f641ad1b9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json @@ -0,0 +1,7 @@ +{ + "id": "202", + "sku_id": "202", + "name": "Window Cleaner Spray", + "description": "Streak-free window cleaner great for glass surfaces. Comes in a 22 oz spray bottle with a pleasant citrus scent.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json new file mode 100644 index 0000000000..3c82f987c0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json @@ -0,0 +1,7 @@ +{ + "id": "203", + "sku_id": "203", + "name": "Dish Soap", + "description": "Concentrated formula cuts through grease and grime on dishes and kitchenware. Comes in a 16 oz bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json new file mode 100644 index 0000000000..371f17c166 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json @@ -0,0 +1,7 @@ +{ + "id": "204", + "sku_id": "204", + "name": "Bathroom Cleaner Spray", + "description": "Powerful cleaner designed for bathroom surfaces. Effectively removes soap scum and hard water stains. 26 oz spray bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json new file mode 100644 index 0000000000..e46a3b5f46 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json @@ -0,0 +1,7 @@ +{ + "id": "205", + "sku_id": "205", + "name": "Laundry Detergent Pods", + "description": "Convenient laundry detergent pods for a powerful clean. 20-pack of scent-free pods suitable for all machines.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json new file mode 100644 index 0000000000..d35b33e7ee --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json @@ -0,0 +1,7 @@ +{ + "id": "206", + "sku_id": "206", + "name": "Heavy-Duty Scrub Sponges", + "description": "Durable scrub sponges ideal for tough stains on pots and pans. Pack of 6 sponges.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json new file mode 100644 index 0000000000..fdbd29c5cd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json @@ -0,0 +1,7 @@ +{ + "id": "207", + "sku_id": "207", + "name": "Disinfecting Wipes", + "description": "Convenient wipes designed to kill 99.9% of germs. Great for quick clean-ups, 75-count tub.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json new file mode 100644 index 0000000000..ac06be7325 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json @@ -0,0 +1,7 @@ +{ + "id": "208", + "sku_id": "208", + "name": "Mop and Broom Set", + "description": "Essential cleaning set that includes a mop and broom. Perfect for keeping floors clean and tidy.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json new file mode 100644 index 0000000000..0e1ce281ac --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json @@ -0,0 +1,7 @@ +{ + "id": "209", + "sku_id": "209", + "name": "Stainless Steel Cleaner", + "description": "Specially formulated cleaner for stainless steel appliances. Restores shine and protects surfaces. 12 oz spray.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json new file mode 100644 index 0000000000..8a0c1ed1c7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json @@ -0,0 +1,7 @@ +{ + "id": "210", + "sku_id": "210", + "name": "Carpet Stain Remover", + "description": "Effective stain remover for carpets and upholstery. Safe for use on most fabrics. 32 oz bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json new file mode 100644 index 0000000000..afbf15894c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json @@ -0,0 +1,7 @@ +{ + "id": "211", + "sku_id": "211", + "name": "Odor Eliminating Spray", + "description": "Quick-acting spray that eliminates persistent odors in the home. 15 oz can with a fresh fragrance.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json new file mode 100644 index 0000000000..c896a2b6b0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json @@ -0,0 +1,7 @@ +{ + "id": "212", + "sku_id": "212", + "name": "Microfiber Cleaning Cloths", + "description": "Soft microfiber cloths for dusting and polishing surfaces. Pack of 5 reusable cloths.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json new file mode 100644 index 0000000000..dd4d0ec8fc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json @@ -0,0 +1,7 @@ +{ + "id": "213", + "sku_id": "213", + "name": "Glass Cleaner with Vinegar", + "description": "Natural glass cleaner made with vinegar for a streak-free shine. 24 oz spray bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json new file mode 100644 index 0000000000..59876c35bf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json @@ -0,0 +1,7 @@ +{ + "id": "214", + "sku_id": "214", + "name": "Air Freshener Spray", + "description": "Odor-neutralizing spray that leaves a light fragrance in the air. 8 oz can available in various scents.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json new file mode 100644 index 0000000000..ea87ad542d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json @@ -0,0 +1,7 @@ +{ + "id": "215", + "sku_id": "215", + "name": "Toilet Bowl Cleaner", + "description": "Powerful toilet bowl cleaner that breaks down stains and eliminates odors. 24 oz bottle with a precision neck for easy application.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json new file mode 100644 index 0000000000..023267222a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json @@ -0,0 +1,7 @@ +{ + "id": "216", + "sku_id": "216", + "name": "Allergen Reducer Spray", + "description": "Spray that helps reduce allergens in the home, including dust and pet dander. 10 oz bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json new file mode 100644 index 0000000000..baa64387e4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json @@ -0,0 +1,7 @@ +{ + "id": "217", + "sku_id": "217", + "name": "Scented Garbage Bags", + "description": "Strong and durable garbage bags infused with a pleasant scent. 30-count box of 13-gallon bags.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json new file mode 100644 index 0000000000..562f8510f0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json @@ -0,0 +1,7 @@ +{ + "id": "218", + "sku_id": "218", + "name": "Floor Cleaner Concentrate", + "description": "Concentrated floor cleaner for all hard surfaces. Makes 4 gallons of cleaner per bottle. 32 oz.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json new file mode 100644 index 0000000000..ae95d251b2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json @@ -0,0 +1,7 @@ +{ + "id": "219", + "sku_id": "219", + "name": "Foam Bathroom Cleaner", + "description": "Thick foam cleaner that clings to surfaces for maximum cleaning power. 19 oz aerosol can.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json new file mode 100644 index 0000000000..f771c63f9b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json @@ -0,0 +1,7 @@ +{ + "id": "220", + "sku_id": "220", + "name": "Heavy Duty Trash Bags", + "description": "Extra thick trash bags designed for heavy loads. 30-count box of 30-gallon bags for tough clean-up tasks.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json new file mode 100644 index 0000000000..b5bc3c35b9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json @@ -0,0 +1,7 @@ +{ + "id": "221", + "sku_id": "221", + "name": "Baking Soda Cleaning Powder", + "description": "A natural cleaner and deodorizer for various household tasks. 16 oz container of pure baking soda.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json new file mode 100644 index 0000000000..5632ccbb76 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json @@ -0,0 +1,7 @@ +{ + "id": "222", + "sku_id": "222", + "name": "Fabric Freshener Spray", + "description": "A fabric freshening spray that neutralizes odors and refreshes upholstery. 13 oz bottle available in multiple scents.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json new file mode 100644 index 0000000000..20c163aac4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json @@ -0,0 +1,7 @@ +{ + "id": "223", + "sku_id": "223", + "name": "Dishwasher Cleaner Tablets", + "description": "Tablets for cleaning the inside of your dishwasher for better performance. 6-count pack.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json new file mode 100644 index 0000000000..117e05eabf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json @@ -0,0 +1,7 @@ +{ + "id": "224", + "sku_id": "224", + "name": "Auto Interior Cleaner", + "description": "Specially formulated cleaner for car interiors, leaves a fresh scent. 16 oz spray bottle.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json new file mode 100644 index 0000000000..caeaff1cc7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json @@ -0,0 +1,7 @@ +{ + "id": "225", + "sku_id": "225", + "name": "Hardwood Floor Cleaner", + "description": "Gentle cleaner designed specifically for hardwood floors. 32 oz bottle, leaves no residue.", + "department": "cleaning" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json new file mode 100644 index 0000000000..f1e546490c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json @@ -0,0 +1,7 @@ +{ + "id": "301", + "sku_id": "301", + "name": "Whole Milk", + "description": "Fresh whole milk, 1 gallon, sourced from local farms.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json new file mode 100644 index 0000000000..697aeac06d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json @@ -0,0 +1,7 @@ +{ + "id": "302", + "sku_id": "302", + "name": "2% Milk", + "description": "Low-fat milk with 2% milkfat, 1 gallon, perfect for everyday use.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json new file mode 100644 index 0000000000..824c4e261a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json @@ -0,0 +1,7 @@ +{ + "id": "303", + "sku_id": "303", + "name": "Almond Milk", + "description": "Unsweetened almond milk, 64 oz, a great dairy alternative for lactose intolerant individuals.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json new file mode 100644 index 0000000000..c84a6c9c17 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json @@ -0,0 +1,7 @@ +{ + "id": "304", + "sku_id": "304", + "name": "Greek Yogurt", + "description": "Creamy and rich Greek yogurt, 32 oz, available in various flavors.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json new file mode 100644 index 0000000000..24daa19b7a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json @@ -0,0 +1,7 @@ +{ + "id": "305", + "sku_id": "305", + "name": "Cottage Cheese", + "description": "Low-fat cottage cheese, 16 oz, high in protein and perfect for snacking.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json new file mode 100644 index 0000000000..6fb546f7a3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json @@ -0,0 +1,7 @@ +{ + "id": "306", + "sku_id": "306", + "name": "Cream Cheese", + "description": "Soft and spreadable cream cheese, 8 oz, perfect for bagels and dips.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json new file mode 100644 index 0000000000..f0ff835ef3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json @@ -0,0 +1,7 @@ +{ + "id": "307", + "sku_id": "307", + "name": "Butter", + "description": "Salted butter, 1 lb, from grass-fed cows, ideal for cooking and baking.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json new file mode 100644 index 0000000000..df86e589f5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json @@ -0,0 +1,7 @@ +{ + "id": "308", + "sku_id": "308", + "name": "Cheddar Cheese", + "description": "Sharp cheddar cheese, 8 oz, great for sandwiches and cheese boards.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json new file mode 100644 index 0000000000..338a286edc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json @@ -0,0 +1,7 @@ +{ + "id": "309", + "sku_id": "309", + "name": "Mozzarella Cheese", + "description": "Fresh mozzarella cheese, 8 oz, perfect for pizza and salads.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json new file mode 100644 index 0000000000..436126bbe5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json @@ -0,0 +1,7 @@ +{ + "id": "310", + "sku_id": "310", + "name": "Parmesan Cheese", + "description": "Grated Parmesan cheese, 8 oz, perfect for adding flavor to dishes.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json new file mode 100644 index 0000000000..e7f26fef18 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json @@ -0,0 +1,7 @@ +{ + "id": "311", + "sku_id": "311", + "name": "Sour Cream", + "description": "Rich and creamy sour cream, 16 oz, perfect for toppings and dips.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json new file mode 100644 index 0000000000..65ef141fb2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json @@ -0,0 +1,7 @@ +{ + "id": "312", + "sku_id": "312", + "name": "Ice Cream", + "description": "Vanilla ice cream, 1.5 quart, a classic dessert favorite.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json new file mode 100644 index 0000000000..0daada5d6a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json @@ -0,0 +1,7 @@ +{ + "id": "313", + "sku_id": "313", + "name": "Heavy Whipping Cream", + "description": "Heavy cream, 16 oz, ideal for whipping and cooking.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json new file mode 100644 index 0000000000..4576185b39 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json @@ -0,0 +1,7 @@ +{ + "id": "314", + "sku_id": "314", + "name": "Goat Cheese", + "description": "Soft goat cheese, 5 oz, great for spreads and salads.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json new file mode 100644 index 0000000000..ca185b970a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json @@ -0,0 +1,7 @@ +{ + "id": "315", + "sku_id": "315", + "name": "Yogurt Parfait", + "description": "Layered yogurt parfait with granola and berries, 12 oz, a great snack.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json new file mode 100644 index 0000000000..556ad5eb80 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json @@ -0,0 +1,7 @@ +{ + "id": "316", + "sku_id": "316", + "name": "Ricotta Cheese", + "description": "Creamy ricotta cheese, 15 oz, perfect for pasta dishes and desserts.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json new file mode 100644 index 0000000000..ea4c74c117 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json @@ -0,0 +1,7 @@ +{ + "id": "317", + "sku_id": "317", + "name": "Buttermilk", + "description": "Cultured buttermilk, 32 oz, great for baking and cooking.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json new file mode 100644 index 0000000000..aa3c135ec6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json @@ -0,0 +1,7 @@ +{ + "id": "318", + "sku_id": "318", + "name": "Almond Milk Yogurt", + "description": "Dairy-free almond yogurt, 5.3 oz, available in various flavors.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json new file mode 100644 index 0000000000..6880f1f155 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json @@ -0,0 +1,7 @@ +{ + "id": "319", + "sku_id": "319", + "name": "Skim Milk", + "description": "Fat-free skim milk, 1 gallon, perfect for a low-calorie diet.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json new file mode 100644 index 0000000000..0afd69e944 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json @@ -0,0 +1,7 @@ +{ + "id": "320", + "sku_id": "320", + "name": "String Cheese", + "description": "Mozzarella string cheese, 12 count, a convenient snack for kids.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json new file mode 100644 index 0000000000..2c63b476a2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json @@ -0,0 +1,7 @@ +{ + "id": "321", + "sku_id": "321", + "name": "Kefir", + "description": "Probiotic rich kefir, 32 oz, a great addition to smoothies.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json new file mode 100644 index 0000000000..ca3ef6c6e8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json @@ -0,0 +1,7 @@ +{ + "id": "322", + "sku_id": "322", + "name": "Tofu Cream Cheese", + "description": "Vegan cream cheese made from tofu, 8 oz, a great dairy alternative.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json new file mode 100644 index 0000000000..2353430c25 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json @@ -0,0 +1,7 @@ +{ + "id": "323", + "sku_id": "323", + "name": "Frozen Yogurt", + "description": "Soft-serve frozen yogurt, 1.5 quart, available in assorted flavors.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json new file mode 100644 index 0000000000..cfb68604d3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json @@ -0,0 +1,7 @@ +{ + "id": "324", + "sku_id": "324", + "name": "Plant-Based Milk", + "description": "Oat milk, 64 oz, a creamy dairy alternative, ideal for coffee.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json new file mode 100644 index 0000000000..7ef0ff94fc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json @@ -0,0 +1,7 @@ +{ + "id": "325", + "sku_id": "325", + "name": "Flavored Creamer", + "description": "Vanilla flavored coffee creamer, 16 oz, perfect for enhancing your morning brew.", + "department": "dairy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json new file mode 100644 index 0000000000..beb7588a97 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json @@ -0,0 +1,7 @@ +{ + "id": "401", + "sku_id": "401", + "name": "Honey Glazed Ham", + "description": "Delicious honey glazed ham, perfect for sandwiches or as a centerpiece.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json new file mode 100644 index 0000000000..bb67fd88d4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json @@ -0,0 +1,7 @@ +{ + "id": "402", + "sku_id": "402", + "name": "Turkey Breast", + "description": "Oven-roasted turkey breast, low in fat and high in flavor.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json new file mode 100644 index 0000000000..05b3ff5af3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json @@ -0,0 +1,7 @@ +{ + "id": "403", + "sku_id": "403", + "name": "Italian Salami", + "description": "A blend of seasoned pork and beef, perfect for antipasto platters.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json new file mode 100644 index 0000000000..46f7a425a2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json @@ -0,0 +1,7 @@ +{ + "id": "404", + "sku_id": "404", + "name": "Sliced Provolone Cheese", + "description": "Creamy provolone cheese slices, great for sandwiches or cheese boards.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json new file mode 100644 index 0000000000..ad27b38b94 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json @@ -0,0 +1,7 @@ +{ + "id": "405", + "sku_id": "405", + "name": "Roast Beef", + "description": "Flavorful roast beef, cut thin for easy stacking on sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json new file mode 100644 index 0000000000..4226e9ec40 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json @@ -0,0 +1,7 @@ +{ + "id": "406", + "sku_id": "406", + "name": "Black Forest Ham", + "description": "Rich and flavorful Black Forest ham, ideal for lunchtime favorites.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json new file mode 100644 index 0000000000..a0bb034139 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json @@ -0,0 +1,7 @@ +{ + "id": "407", + "sku_id": "407", + "name": "Genoa Salami", + "description": "Authentic Genoa salami, mildly spiced, perfect for charcuterie boards.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json new file mode 100644 index 0000000000..47d0a96513 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json @@ -0,0 +1,7 @@ +{ + "id": "408", + "sku_id": "408", + "name": "Bacon Bits", + "description": "Crispy bacon bits, perfect for toppings on salads or baked potatoes.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json new file mode 100644 index 0000000000..2c745ad0d8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json @@ -0,0 +1,7 @@ +{ + "id": "409", + "sku_id": "409", + "name": "Pepper Jack Cheese", + "description": "Spicy pepper jack cheese, great for melting or adding flavor to dishes.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json new file mode 100644 index 0000000000..0e919cfba3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json @@ -0,0 +1,7 @@ +{ + "id": "410", + "sku_id": "410", + "name": "Sliced Swiss Cheese", + "description": "Smooth Swiss cheese, perfect for sandwiches or snacking.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json new file mode 100644 index 0000000000..8d667f48d6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json @@ -0,0 +1,7 @@ +{ + "id": "411", + "sku_id": "411", + "name": "Meatloaf Slice", + "description": "Homemade meatloaf slices, ready to heat and serve for a quick meal.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json new file mode 100644 index 0000000000..65c8c0688b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json @@ -0,0 +1,7 @@ +{ + "id": "412", + "sku_id": "412", + "name": "Hummus Spread", + "description": "Creamy hummus spread made with fresh chickpeas and tahini, perfect for dipping.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json new file mode 100644 index 0000000000..a759429e6c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json @@ -0,0 +1,7 @@ +{ + "id": "413", + "sku_id": "413", + "name": "Sliced Chicken Breast", + "description": "Tender chicken breast, perfect for salads or sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json new file mode 100644 index 0000000000..fd34eb00f3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json @@ -0,0 +1,7 @@ +{ + "id": "414", + "sku_id": "414", + "name": "Pimento Cheese Spread", + "description": "Savory pimento cheese spread, great with crackers or veggies.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json new file mode 100644 index 0000000000..0905d67d5f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json @@ -0,0 +1,7 @@ +{ + "id": "415", + "sku_id": "415", + "name": "Tuna Salad", + "description": "Freshly made tuna salad with mayonnaise and seasoning, perfect for sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json new file mode 100644 index 0000000000..10d8c0fa84 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json @@ -0,0 +1,7 @@ +{ + "id": "416", + "sku_id": "416", + "name": "Baked Ham & Cheese Sandwich", + "description": "Delicious baked ham and cheese sandwich, ready for a quick meal.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json new file mode 100644 index 0000000000..7b56286cb5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json @@ -0,0 +1,7 @@ +{ + "id": "417", + "sku_id": "417", + "name": "Antipasto Salad", + "description": "Mixed antipasto salad with olives, peppers, and meats, ideal for sharing.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json new file mode 100644 index 0000000000..449d61cb98 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json @@ -0,0 +1,7 @@ +{ + "id": "418", + "sku_id": "418", + "name": "Mediterranean Wrap", + "description": "Flavorful wrap filled with turkey, cheese, and Mediterranean veggies.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json new file mode 100644 index 0000000000..f3d10ec712 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json @@ -0,0 +1,7 @@ +{ + "id": "419", + "sku_id": "419", + "name": "BBQ Chicken Sandwich", + "description": "Pulled BBQ chicken on a bun, perfect for lunch or a light meal.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json new file mode 100644 index 0000000000..3ade7745bb --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json @@ -0,0 +1,7 @@ +{ + "id": "420", + "sku_id": "420", + "name": "Sliced Roast Pork", + "description": "Tender, slow-roasted pork, perfect for sandwiches or as a main dish.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json new file mode 100644 index 0000000000..b91236adf8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json @@ -0,0 +1,7 @@ +{ + "id": "421", + "sku_id": "421", + "name": "Cranberry Chicken Salad", + "description": "Chicken salad with cranberries, nuts, and dressing, perfect for sandwiches.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json new file mode 100644 index 0000000000..b3ff27b9d4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json @@ -0,0 +1,7 @@ +{ + "id": "422", + "sku_id": "422", + "name": "Shrimp Salad", + "description": "Fresh shrimp salad with a tangy dressing, ideal for seafood lovers.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json new file mode 100644 index 0000000000..0fa271b50f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json @@ -0,0 +1,7 @@ +{ + "id": "423", + "sku_id": "423", + "name": "Caprese Sandwich", + "description": "A classic Caprese sandwich with fresh mozzarella, tomatoes, and basil.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json new file mode 100644 index 0000000000..9825fb8a62 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json @@ -0,0 +1,7 @@ +{ + "id": "424", + "sku_id": "424", + "name": "Curried Egg Salad", + "description": "Egg salad mixed with curry spices, great on its own or in a sandwich.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json new file mode 100644 index 0000000000..0fe110bb1d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json @@ -0,0 +1,7 @@ +{ + "id": "425", + "sku_id": "425", + "name": "Veggie Platter with Dip", + "description": "A colorful assortment of fresh veggies served with a tasty dip.", + "department": "deli" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json new file mode 100644 index 0000000000..910bdf1789 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json @@ -0,0 +1,7 @@ +{ + "id": "501", + "sku_id": "501", + "name": "Grass-Fed Beef Steak", + "description": "Premium grass-fed beef steak, tender and flavorful. Perfect for grilling or pan-searing.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json new file mode 100644 index 0000000000..d1445449ef --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json @@ -0,0 +1,7 @@ +{ + "id": "502", + "sku_id": "502", + "name": "Organic Chicken Breast", + "description": "Juicy organic chicken breasts, free-range and hormone-free, perfect for healthy meals.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json new file mode 100644 index 0000000000..e24f1c6d20 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json @@ -0,0 +1,7 @@ +{ + "id": "503", + "sku_id": "503", + "name": "Pork Tenderloin", + "description": "Lean and tender pork tenderloin, ideal for roasting or grilling, packed with flavor.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json new file mode 100644 index 0000000000..55d724f62b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json @@ -0,0 +1,7 @@ +{ + "id": "504", + "sku_id": "504", + "name": "Bacon Strips", + "description": "Crispy, smoky bacon strips made from premium pork, great for breakfast sandwiches.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json new file mode 100644 index 0000000000..b7635a3a79 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json @@ -0,0 +1,7 @@ +{ + "id": "505", + "sku_id": "505", + "name": "Ground Turkey", + "description": "Lean ground turkey, versatile and nutritious, perfect for burgers or meatballs.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json new file mode 100644 index 0000000000..7d21297390 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json @@ -0,0 +1,7 @@ +{ + "id": "506", + "sku_id": "506", + "name": "Salmon Fillet", + "description": "Fresh Atlantic salmon fillet, rich in omega-3 fatty acids, perfect for grilling or baking.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json new file mode 100644 index 0000000000..f34f146088 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json @@ -0,0 +1,7 @@ +{ + "id": "507", + "sku_id": "507", + "name": "Beef Brisket", + "description": "Flavorful beef brisket, great for slow cooking or barbecuing, melts in your mouth.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json new file mode 100644 index 0000000000..deb47771f2 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json @@ -0,0 +1,7 @@ +{ + "id": "508", + "sku_id": "508", + "name": "Chicken Thighs", + "description": "Tender chicken thighs, skin-on and bone-in for maximum flavor, great for roasting.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json new file mode 100644 index 0000000000..a279a24ac5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json @@ -0,0 +1,7 @@ +{ + "id": "509", + "sku_id": "509", + "name": "Italian Sausage Links", + "description": "Savory Italian sausage links, made with herbs and spices, perfect for grilling or pasta dishes.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json new file mode 100644 index 0000000000..7bebdb00df --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json @@ -0,0 +1,7 @@ +{ + "id": "510", + "sku_id": "510", + "name": "Lamb Chops", + "description": "Juicy lamb chops, expertly cut and seasoned, ideal for grilling or pan-searing.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json new file mode 100644 index 0000000000..c571653867 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json @@ -0,0 +1,7 @@ +{ + "id": "511", + "sku_id": "511", + "name": "Turkey Bacon", + "description": "Lean turkey bacon, a healthier alternative to pork bacon without compromising on taste.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json new file mode 100644 index 0000000000..8c781c2c18 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json @@ -0,0 +1,7 @@ +{ + "id": "512", + "sku_id": "512", + "name": "Whole Chicken", + "description": "Fresh whole chicken, ideal for roasting or slow-cooking, feeds the whole family.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json new file mode 100644 index 0000000000..895a46dffe --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json @@ -0,0 +1,7 @@ +{ + "id": "513", + "sku_id": "513", + "name": "Beef Short Ribs", + "description": "Rich and flavorful beef short ribs, perfect for braising or slow-cooking.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json new file mode 100644 index 0000000000..afa28d663a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json @@ -0,0 +1,7 @@ +{ + "id": "514", + "sku_id": "514", + "name": "Smoked Sausage", + "description": "Delicious smoked sausage, great for grilling or adding to stews and casseroles.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json new file mode 100644 index 0000000000..a847c7974f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json @@ -0,0 +1,7 @@ +{ + "id": "515", + "sku_id": "515", + "name": "Deli Ham", + "description": "Premium deli ham, perfect for sandwiches and charcuterie boards.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json new file mode 100644 index 0000000000..ae73b95cf6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json @@ -0,0 +1,7 @@ +{ + "id": "516", + "sku_id": "516", + "name": "Fish Filet (Tilapia)", + "description": "Mild-tasting tilapia filets, perfect for baking or frying.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json new file mode 100644 index 0000000000..556444822c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json @@ -0,0 +1,7 @@ +{ + "id": "517", + "sku_id": "517", + "name": "Chicken Wings", + "description": "Flavorful chicken wings, perfect for frying or baking with your favorite sauces.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json new file mode 100644 index 0000000000..a81848c2c8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json @@ -0,0 +1,7 @@ +{ + "id": "518", + "sku_id": "518", + "name": "Pork Chops", + "description": "Juicy pork loin chops, perfect for grilling or sautéing, seasoned to perfection.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json new file mode 100644 index 0000000000..a6680a738a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json @@ -0,0 +1,7 @@ +{ + "id": "519", + "sku_id": "519", + "name": "Duck Breast", + "description": "Succulent duck breast, ideal for gourmet meals, rich in flavor and tender.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json new file mode 100644 index 0000000000..c910604383 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json @@ -0,0 +1,7 @@ +{ + "id": "520", + "sku_id": "520", + "name": "Salami Slices", + "description": "Delicious salami slices, great for sandwiches or snacking on cheese plates.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json new file mode 100644 index 0000000000..cd0e9aa052 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json @@ -0,0 +1,7 @@ +{ + "id": "521", + "sku_id": "521", + "name": "Beef Meatballs", + "description": "Savory beef meatballs, perfect for pasta dishes or as an appetizer.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json new file mode 100644 index 0000000000..1b74b6f93e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json @@ -0,0 +1,7 @@ +{ + "id": "522", + "sku_id": "522", + "name": "Fish Filet (Cod)", + "description": "Fresh cod filets, versatile and mild in flavor, ideal for a variety of recipes.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json new file mode 100644 index 0000000000..3ea87bcfea --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json @@ -0,0 +1,7 @@ +{ + "id": "523", + "sku_id": "523", + "name": "Spicy Chorizo", + "description": "Flavor-packed spicy chorizo sausage, great for tacos, pasta, or breakfast dishes.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json new file mode 100644 index 0000000000..5ef84adb20 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json @@ -0,0 +1,7 @@ +{ + "id": "524", + "sku_id": "524", + "name": "Corned Beef Brisket", + "description": "Tender corned beef brisket, perfect for sandwiches or classic home-cooked meals.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json new file mode 100644 index 0000000000..cdf848f7a5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json @@ -0,0 +1,7 @@ +{ + "id": "525", + "sku_id": "525", + "name": "Sliced Roast Beef", + "description": "Premium sliced roast beef, perfect for sandwiches or as part of a charcuterie spread.", + "department": "meat" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json new file mode 100644 index 0000000000..3b1ff2345a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json @@ -0,0 +1,7 @@ +{ + "id": "601", + "sku_id": "601", + "name": "Ibuprofen 200mg", + "description": "Relieves pain, reduces inflammation, and lowers fever. Over-the-counter pain reliever.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json new file mode 100644 index 0000000000..1b67263192 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json @@ -0,0 +1,7 @@ +{ + "id": "602", + "sku_id": "602", + "name": "Cetirizine 10mg", + "description": "Antihistamine for allergy relief. Helps alleviate symptoms like sneezing and runny nose.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json new file mode 100644 index 0000000000..878de27ad7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json @@ -0,0 +1,7 @@ +{ + "id": "603", + "sku_id": "603", + "name": "Lisinopril 10mg", + "description": "Medication used to treat high blood pressure and heart failure.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json new file mode 100644 index 0000000000..7282b041a8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json @@ -0,0 +1,7 @@ +{ + "id": "604", + "sku_id": "604", + "name": "Metformin 500mg", + "description": "Oral medication for diabetes management, helps control blood sugar levels.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json new file mode 100644 index 0000000000..3399a6b792 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json @@ -0,0 +1,7 @@ +{ + "id": "605", + "sku_id": "605", + "name": "Aspirin 81mg", + "description": "Low-dose aspirin for heart health, helps prevent blood clots.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json new file mode 100644 index 0000000000..4dc7b7e5bc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json @@ -0,0 +1,7 @@ +{ + "id": "606", + "sku_id": "606", + "name": "Amoxicillin 500mg", + "description": "Antibiotic used to treat various infections, including respiratory and skin infections.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json new file mode 100644 index 0000000000..c79909bc83 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json @@ -0,0 +1,7 @@ +{ + "id": "607", + "sku_id": "607", + "name": "Simvastatin 20mg", + "description": "Cholesterol-lowering medication that helps reduce heart disease risk.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json new file mode 100644 index 0000000000..b2c6b0a360 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json @@ -0,0 +1,7 @@ +{ + "id": "608", + "sku_id": "608", + "name": "Pantoprazole 40mg", + "description": "Proton pump inhibitor used to treat gastroesophageal reflux disease (GERD).", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json new file mode 100644 index 0000000000..3f5a654ef1 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json @@ -0,0 +1,7 @@ +{ + "id": "609", + "sku_id": "609", + "name": "Levothyroxine 100mcg", + "description": "Thyroid hormone replacement therapy for hypothyroidism.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json new file mode 100644 index 0000000000..5d905183c8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json @@ -0,0 +1,7 @@ +{ + "id": "610", + "sku_id": "610", + "name": "Alprazolam 0.25mg", + "description": "Medication used to treat anxiety and panic disorders.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json new file mode 100644 index 0000000000..1eb4d7f4cf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json @@ -0,0 +1,7 @@ +{ + "id": "611", + "sku_id": "611", + "name": "Omeprazole 20mg", + "description": "Proton pump inhibitor used for treating stomach ulcers and acid reflux.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json new file mode 100644 index 0000000000..cfd52252f8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json @@ -0,0 +1,7 @@ +{ + "id": "612", + "sku_id": "612", + "name": "Hydrochlorothiazide 12.5mg", + "description": "Diuretic used to treat high blood pressure and fluid retention.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json new file mode 100644 index 0000000000..1ba3d39bff --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json @@ -0,0 +1,7 @@ +{ + "id": "613", + "sku_id": "613", + "name": "Zolpidem 10mg", + "description": "Medication for short-term treatment of insomnia.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json new file mode 100644 index 0000000000..41302ac062 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json @@ -0,0 +1,7 @@ +{ + "id": "614", + "sku_id": "614", + "name": "Insulin Glargine 100 units/ml", + "description": "Long-acting insulin for blood sugar control in diabetes.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json new file mode 100644 index 0000000000..345ad2b976 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json @@ -0,0 +1,7 @@ +{ + "id": "615", + "sku_id": "615", + "name": "Dextromethorphan 10mg", + "description": "Cough suppressant effective in treating dry cough.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json new file mode 100644 index 0000000000..8482c3e3d5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json @@ -0,0 +1,7 @@ +{ + "id": "616", + "sku_id": "616", + "name": "Guaifenesin 600mg", + "description": "Expectorant that helps relieve chest congestion by thinning mucus.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json new file mode 100644 index 0000000000..7f9025902b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json @@ -0,0 +1,7 @@ +{ + "id": "617", + "sku_id": "617", + "name": "Naproxen 250mg", + "description": "Nonsteroidal anti-inflammatory drug (NSAID) for pain relief.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json new file mode 100644 index 0000000000..ef2cd1e563 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json @@ -0,0 +1,7 @@ +{ + "id": "618", + "sku_id": "618", + "name": "Clonazepam 0.5mg", + "description": "Medication used to treat seizure disorders and panic disorders.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json new file mode 100644 index 0000000000..e4b3df7772 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json @@ -0,0 +1,7 @@ +{ + "id": "619", + "sku_id": "619", + "name": "Ranitidine 150mg", + "description": "Histamine-2 blocker used to treat heartburn and acid reflux.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json new file mode 100644 index 0000000000..3388c72729 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json @@ -0,0 +1,7 @@ +{ + "id": "620", + "sku_id": "620", + "name": "Montelukast 10mg", + "description": "Medication for asthma and seasonal allergies management.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json new file mode 100644 index 0000000000..5b95fbfaf7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json @@ -0,0 +1,7 @@ +{ + "id": "621", + "sku_id": "621", + "name": "Fexofenadine 180mg", + "description": "Non-drowsy antihistamine for allergy relief.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json new file mode 100644 index 0000000000..731549c119 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json @@ -0,0 +1,7 @@ +{ + "id": "622", + "sku_id": "622", + "name": "Loratadine 10mg", + "description": "Antihistamine used to relieve allergy symptoms without drowsiness.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json new file mode 100644 index 0000000000..52f2d32cb9 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json @@ -0,0 +1,7 @@ +{ + "id": "623", + "sku_id": "623", + "name": "Propranolol 20mg", + "description": "Beta-blocker used to treat high blood pressure and anxiety.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json new file mode 100644 index 0000000000..bf8c990c70 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json @@ -0,0 +1,7 @@ +{ + "id": "624", + "sku_id": "624", + "name": "Levocetirizine 5mg", + "description": "Antihistamine for allergic rhinitis and chronic urticaria (hives).", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json new file mode 100644 index 0000000000..5b5d09c410 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json @@ -0,0 +1,7 @@ +{ + "id": "625", + "sku_id": "625", + "name": "Bupropion 150mg", + "description": "Medication used to treat depression and to help people quit smoking.", + "department": "pharmacy" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json new file mode 100644 index 0000000000..20ee187227 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json @@ -0,0 +1,7 @@ +{ + "id": "701", + "sku_id": "701", + "name": "Organic Gala Apples", + "description": "Fresh organic gala apples, crisp and sweet, perfect for snacks and salads.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json new file mode 100644 index 0000000000..b7aee26faf --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json @@ -0,0 +1,7 @@ +{ + "id": "702", + "sku_id": "702", + "name": "Bananas", + "description": "Ripe yellow bananas, high in potassium and perfect for smoothies or on-the-go snacks.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json new file mode 100644 index 0000000000..83e738a9e7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json @@ -0,0 +1,7 @@ +{ + "id": "703", + "sku_id": "703", + "name": "Strawberries", + "description": "Juicy and sweet strawberries, great for desserts or fresh salads.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json new file mode 100644 index 0000000000..76d7cdaf79 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json @@ -0,0 +1,7 @@ +{ + "id": "704", + "sku_id": "704", + "name": "Baby Spinach", + "description": "Fresh baby spinach, perfect for salads, sandwiches, or adding to smoothies.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json new file mode 100644 index 0000000000..fa8b47aa28 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json @@ -0,0 +1,7 @@ +{ + "id": "705", + "sku_id": "705", + "name": "Carrots", + "description": "Crunchy carrots, perfect for snacking or cooking in your favorite dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json new file mode 100644 index 0000000000..c0df37fc02 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json @@ -0,0 +1,7 @@ +{ + "id": "706", + "sku_id": "706", + "name": "Broccoli Florets", + "description": "Fresh broccoli florets, great for steaming or adding to stir-fries.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json new file mode 100644 index 0000000000..def26da89c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json @@ -0,0 +1,7 @@ +{ + "id": "707", + "sku_id": "707", + "name": "Ripe Avocados", + "description": "Creamy avocados, ideal for guacamole, salads, or spreading on toast.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json new file mode 100644 index 0000000000..e1363147ea --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json @@ -0,0 +1,7 @@ +{ + "id": "708", + "sku_id": "708", + "name": "Red Bell Peppers", + "description": "Sweet and crunchy red bell peppers, perfect for salads or grilling.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json new file mode 100644 index 0000000000..3643a0c1dc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json @@ -0,0 +1,7 @@ +{ + "id": "709", + "sku_id": "709", + "name": "Seedless Cucumbers", + "description": "Fresh seedless cucumbers, great for salads, sandwiches, or just snacking.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json new file mode 100644 index 0000000000..466da35f3e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json @@ -0,0 +1,7 @@ +{ + "id": "710", + "sku_id": "710", + "name": "Fresh Basil", + "description": "Aromatic fresh basil, perfect for garnishing or adding flavor to dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json new file mode 100644 index 0000000000..61b829b914 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json @@ -0,0 +1,7 @@ +{ + "id": "711", + "sku_id": "711", + "name": "Green Grapes", + "description": "Sweet and juicy green grapes, great for snacking or adding to fruit salads.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json new file mode 100644 index 0000000000..866b0915b3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json @@ -0,0 +1,7 @@ +{ + "id": "712", + "sku_id": "712", + "name": "Pineapple", + "description": "Fresh pineapple, tropical and sweet, ideal for fresh-cut fruit or smoothies.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json new file mode 100644 index 0000000000..8c151aee8f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json @@ -0,0 +1,7 @@ +{ + "id": "713", + "sku_id": "713", + "name": "Lemons", + "description": "Fresh lemons, perfect for lemonade, cooking, or flavoring drinks.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json new file mode 100644 index 0000000000..39215a7710 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json @@ -0,0 +1,7 @@ +{ + "id": "714", + "sku_id": "714", + "name": "Zucchini", + "description": "Tender zucchini, versatile for grilling, baking, and stir-frying.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json new file mode 100644 index 0000000000..46b1e14840 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json @@ -0,0 +1,7 @@ +{ + "id": "715", + "sku_id": "715", + "name": "Red Potatoes", + "description": "Nutritious red potatoes, great for baking, boiling, or roasting.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json new file mode 100644 index 0000000000..e53c9733cd --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json @@ -0,0 +1,7 @@ +{ + "id": "716", + "sku_id": "716", + "name": "Sweet Potatoes", + "description": "Delicious sweet potatoes, perfect for baking or mashing.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json new file mode 100644 index 0000000000..ab48ac1c6f --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json @@ -0,0 +1,7 @@ +{ + "id": "717", + "sku_id": "717", + "name": "Cauliflower", + "description": "Fresh cauliflower, perfect for roasting or using in low-carb dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json new file mode 100644 index 0000000000..42cba51bd7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json @@ -0,0 +1,7 @@ +{ + "id": "718", + "sku_id": "718", + "name": "Green Beans", + "description": "Crispy green beans, great for sautéing or enjoying as a side dish.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json new file mode 100644 index 0000000000..4d035df9a4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json @@ -0,0 +1,7 @@ +{ + "id": "719", + "sku_id": "719", + "name": "Kale", + "description": "Nutritious kale, perfect for salads or smoothies packed with vitamins.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json new file mode 100644 index 0000000000..c81e7d0ade --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json @@ -0,0 +1,7 @@ +{ + "id": "720", + "sku_id": "720", + "name": "Onions", + "description": "Fresh onions, essential for cooking and adding flavor to many dishes.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json new file mode 100644 index 0000000000..86e1ab11c8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json @@ -0,0 +1,7 @@ +{ + "id": "721", + "sku_id": "721", + "name": "Garlic", + "description": "Fresh garlic, a must-have for enhancing the flavor of your meals.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json new file mode 100644 index 0000000000..6d4dc5fe99 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json @@ -0,0 +1,7 @@ +{ + "id": "722", + "sku_id": "722", + "name": "Mangoes", + "description": "Juicy mangoes, sweet and tropical, great for snacking or smoothies.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json new file mode 100644 index 0000000000..06f2691bb8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json @@ -0,0 +1,7 @@ +{ + "id": "723", + "sku_id": "723", + "name": "Cherries", + "description": "Sweet cherries, perfect for desserts or eating fresh.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json new file mode 100644 index 0000000000..ebcba25b10 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json @@ -0,0 +1,7 @@ +{ + "id": "724", + "sku_id": "724", + "name": "Raspberries", + "description": "Fresh raspberries, sweet and tart, ideal for snacking or baking.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json new file mode 100644 index 0000000000..a2a420db93 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json @@ -0,0 +1,7 @@ +{ + "id": "725", + "sku_id": "725", + "name": "Blackberries", + "description": "Juicy blackberries, perfect for adding to desserts or enjoying fresh.", + "department": "produce" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json new file mode 100644 index 0000000000..47562d3999 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json @@ -0,0 +1,7 @@ +{ + "id": "801", + "sku_id": "801", + "name": "Wild Caught Salmon Fillet", + "description": "Delicious and healthy wild caught salmon fillet, rich in omega-3 fatty acids. Perfect for grilling or baking.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json new file mode 100644 index 0000000000..3938bd8d53 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json @@ -0,0 +1,7 @@ +{ + "id": "802", + "sku_id": "802", + "name": "Shrimp Cocktail", + "description": "Fresh shrimp served chilled with a side of tangy cocktail sauce. A perfect appetizer for any gathering.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json new file mode 100644 index 0000000000..97cbb2a687 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json @@ -0,0 +1,7 @@ +{ + "id": "803", + "sku_id": "803", + "name": "Fresh Atlantic Cod", + "description": "Mild and flaky Atlantic cod, great for frying or baking. Sustainably sourced and always fresh.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json new file mode 100644 index 0000000000..5e80d88759 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json @@ -0,0 +1,7 @@ +{ + "id": "804", + "sku_id": "804", + "name": "Seared Ahi Tuna Steaks", + "description": "Premium ahi tuna steaks, perfect for searing or sushi. A must-try for tuna lovers.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json new file mode 100644 index 0000000000..9991f8a812 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json @@ -0,0 +1,7 @@ +{ + "id": "805", + "sku_id": "805", + "name": "Maine Lobster Tails", + "description": "Caught in the cool waters of Maine, these lobster tails are sweet, succulent, and perfect for a special dinner.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json new file mode 100644 index 0000000000..ba38374ac3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json @@ -0,0 +1,7 @@ +{ + "id": "806", + "sku_id": "806", + "name": "Sea Bass Fillet", + "description": "Fresh sea bass fillet, known for its delicate texture and mild flavor. Ideal for grilling or pan-searing.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json new file mode 100644 index 0000000000..cd1d7bfc6b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json @@ -0,0 +1,7 @@ +{ + "id": "807", + "sku_id": "807", + "name": "Pacific Mackerel", + "description": "Rich in flavor and healthy fats, Pacific mackerel is perfect for grilling or smoking.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json new file mode 100644 index 0000000000..e8faf12c59 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json @@ -0,0 +1,7 @@ +{ + "id": "808", + "sku_id": "808", + "name": "Organic Blue Crab Meat", + "description": "Sweet and tender organic blue crab meat, perfect for crab cakes or pasta dishes.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json new file mode 100644 index 0000000000..34e4694ecc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json @@ -0,0 +1,7 @@ +{ + "id": "809", + "sku_id": "809", + "name": "Frozen Shrimp (31/40 Count)", + "description": "Frozen, easy-to-peel shrimp, perfect for stir-frys, pasta, or shrimp tacos.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json new file mode 100644 index 0000000000..59fab4aac7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json @@ -0,0 +1,7 @@ +{ + "id": "810", + "sku_id": "810", + "name": "Smoked Salmon Lox", + "description": "Delicious smoked salmon lox, great for bagels, salads, or gourmet dishes.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json new file mode 100644 index 0000000000..35d42c436e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json @@ -0,0 +1,7 @@ +{ + "id": "811", + "sku_id": "811", + "name": "Seafood Medley", + "description": "A delightful mix of shrimp, scallops, and calamari, ideal for pasta, stir-fry, or seafood boils.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json new file mode 100644 index 0000000000..63194b1769 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json @@ -0,0 +1,7 @@ +{ + "id": "812", + "sku_id": "812", + "name": "Fresh Clams (Diners Choice)", + "description": "Select fresh clams, perfect for steaming or in chowders. Freshly harvested from local waters.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json new file mode 100644 index 0000000000..25c63638a4 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json @@ -0,0 +1,7 @@ +{ + "id": "813", + "sku_id": "813", + "name": "Scallops - Jumbo", + "description": "Sweet and tender jumbo scallops, great for grilling or broiling. A true delicacy for seafood lovers.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json new file mode 100644 index 0000000000..91cfdb2fa5 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json @@ -0,0 +1,7 @@ +{ + "id": "814", + "sku_id": "814", + "name": "Canned Tuna (Chunk Light)", + "description": "Canned chunk light tuna in water, perfect for salads, sandwiches, and casseroles.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json new file mode 100644 index 0000000000..1d9617747c --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json @@ -0,0 +1,7 @@ +{ + "id": "815", + "sku_id": "815", + "name": "Whole Fresh Fish (Snapper)", + "description": "Fresh snapper fish, perfect for grilling whole or filleting. Sustainably caught for great quality.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json new file mode 100644 index 0000000000..61a0b1b5e8 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json @@ -0,0 +1,7 @@ +{ + "id": "816", + "sku_id": "816", + "name": "Marinated Anchovies", + "description": "Savory marinated anchovies, great as a topping for salads or as a snack. Rich in protein and flavor.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json new file mode 100644 index 0000000000..e2edb4f2e0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json @@ -0,0 +1,7 @@ +{ + "id": "817", + "sku_id": "817", + "name": "Oysters (Live)", + "description": "Fresh live oysters from the coast, perfect for shucking and enjoying raw or grilled.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json new file mode 100644 index 0000000000..6a14719bde --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json @@ -0,0 +1,7 @@ +{ + "id": "818", + "sku_id": "818", + "name": "Fish Sauce", + "description": "Authentic fish sauce made from fermented fish, essential for Vietnamese and Thai cooking.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json new file mode 100644 index 0000000000..5b2f12d424 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json @@ -0,0 +1,7 @@ +{ + "id": "819", + "sku_id": "819", + "name": "Crab Legs (King)", + "description": "Freshly frozen king crab legs, sweet and succulent, perfect for special occasions.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json new file mode 100644 index 0000000000..e06a342480 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json @@ -0,0 +1,7 @@ +{ + "id": "820", + "sku_id": "820", + "name": "Sushi Grade Salmon", + "description": "High-quality sushi grade salmon, perfect for sashimi or making sushi rolls.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json new file mode 100644 index 0000000000..8c41c284ab --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json @@ -0,0 +1,7 @@ +{ + "id": "821", + "sku_id": "821", + "name": "Smoked Whitefish Salad", + "description": "Creamy smoked whitefish salad, perfect for spreading on crackers or bagels. A delicious snack or appetizer.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json new file mode 100644 index 0000000000..79e42b761b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json @@ -0,0 +1,7 @@ +{ + "id": "822", + "sku_id": "822", + "name": "Fish Tacos Kit", + "description": "Everything you need to make delicious fish tacos, including fresh tortillas, seasoned fish, and toppings.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json new file mode 100644 index 0000000000..8075ad715d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json @@ -0,0 +1,7 @@ +{ + "id": "823", + "sku_id": "823", + "name": "Tuna Poke Bowl Kit", + "description": "A DIY poke bowl kit with sushi-grade tuna, rice, and authentic toppings for a fresh meal.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json new file mode 100644 index 0000000000..b233fc7005 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json @@ -0,0 +1,7 @@ +{ + "id": "824", + "sku_id": "824", + "name": "Sardines (Canned in Olive Oil)", + "description": "Canned sardines in extra virgin olive oil, perfect for salads, pastas, or as a healthy snack.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json new file mode 100644 index 0000000000..c317fddc49 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json @@ -0,0 +1,7 @@ +{ + "id": "825", + "sku_id": "825", + "name": "Fish Stock", + "description": "Rich and flavorful fish stock, perfect for soups and sauces that require a seafood base.", + "department": "seafood" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema new file mode 100644 index 0000000000..7d6ae599b7 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} + \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema new file mode 100644 index 0000000000..0fe6c5999a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema @@ -0,0 +1,24 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "sku_id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "department": { + "type": "string", + "enum": ["appliance", "cleaning", "dairy", "deli", "meat", "pharmacy", "produce", "seafood"] + } + }, + "required": ["id", "sku_id", "name", "description", "department"], + "additionalProperties": false + } + \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json new file mode 100644 index 0000000000..99838a27a3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json @@ -0,0 +1,9 @@ +{ + "id": "1000", + "receipt_id": "1000", + "transaction_date": "2025-04-01 10:30:00", + "customer_id": "50001", + "items": [ + {"sku_id": "101", "units": 0.0, "unit_price": 0.00, "discounts": 0.00} + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json new file mode 100644 index 0000000000..a2c5ef6ffa --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json @@ -0,0 +1,9 @@ +{ + "id": "1001", + "receipt_id": "1001", + "transaction_date": "2025-04-02 08:30:00", + "customer_id": "50001", + "items": [ + {"sku_id": "201", "units": 5.0, "unit_price": 9.99, "discounts": 0.00} + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json new file mode 100644 index 0000000000..10ec3ace73 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json @@ -0,0 +1,9 @@ +{ + "id": "1002", + "receipt_id": "1002", + "transaction_date": "2025-04-02 10:30:08", + "customer_id": "50001", + "items": [ + {"sku_id": "301", "units": 3.0, "unit_price": 9.99, "discounts": 0.00} + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema new file mode 100644 index 0000000000..1dc805ee1b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Purchases Identifier Key", + "description": "A unique identifier for the purchase transaction", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema new file mode 100644 index 0000000000..a25b1a5160 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema @@ -0,0 +1,63 @@ +{ + "title": "Purchase Transaction Record Value", + "description": "Schema for a transaction record containing receipt information, transaction date, and purchased items.", + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Unique identifier for the transaction record." + }, + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the purchase." + }, + "items": { + "type": "array", + "description": "List of items included in the transaction.", + "items": { + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "description": "SKU identifier for the purchased item." + }, + "units": { + "type": "number", + "description": "Number of units purchased." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the item." + }, + "discounts": { + "type": "number", + "description": "Total discounts applied to the item." + } + }, + "required": [ + "sku_id", + "units", + "unit_price", + "discounts" + ] + } + } + }, + "required": [ + "id", + "receipt_id", + "transaction_date", + "items", + "customer_id" + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema new file mode 100644 index 0000000000..b172353823 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema @@ -0,0 +1,5 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema new file mode 100644 index 0000000000..ecbb8c3758 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema @@ -0,0 +1,45 @@ +{ + "title": "Purchase Transactions", + "description": "Flattened Table for all purchases", + "type": "object", + "properties": { + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the purchase." + }, + "sku_id": { + "type": "string", + "description": "SKU identifier for the purchased item." + }, + "units": { + "type": "number", + "description": "Number of units purchased." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the item." + }, + "discounts": { + "type": "number", + "description": "Total discounts applied to the item." + } + }, + "required": [ + "receipt_id", + "transaction_date", + "customer_id", + "sku_id", + "units", + "unit_price", + "discounts" + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json new file mode 100644 index 0000000000..ccd800dcd0 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json @@ -0,0 +1,8 @@ +{ + "id": "3000", + "replenishment_id": "3000", + "transaction_date": "2025-03-31 20:30:00", + "sku_id": "101", + "units": 300.0, + "vendor_id": "30001" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema new file mode 100644 index 0000000000..6a2e0dddcc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Replenishment Identifier Key", + "description": "A unique identifier for the replenishment transaction", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema new file mode 100644 index 0000000000..9386ad46fc --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema @@ -0,0 +1,65 @@ +{ + "title": "ReplenishmentTransaction", + "description": "Schema for a replenishment transaction including ID, transaction date, SKU ID, and units replenished.", + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Unique identifier for the replenishment transaction." + }, + "replenishment_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier linking to the replenishment event." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in YYYY-MM-DD HH:MM:SS format." + }, + "sku_id": { + "type": "string", + "description": "Stock keeping unit (SKU) identifier for the replenished product." + }, + "units": { + "type": "number", + "description": "Number of units replenished during the transaction." + }, + "vendor_id": { + "type": "string", + "description": "Unique identifier for the vendor supplying the product." + }, + "_attachments": { + "type": "string", + "description": "A link to the documents attachments (e.g., media, binary data) if any exist. In most cases, it will just be an empty string unless you actually upload attachments." + }, + "_etag": { + "type": "string", + "description": "The entity tag for optimistic concurrency control. It changes every time the document is updated. Cosmos DB uses it to check if the document has changed since a client last read it." + }, + "_lsn": { + "type": "number", + "description": "Logical Sequence Number. It represents the order in which operations (insert/update/delete) were performed. Used internally for replication and change feed processing." + }, + "_rid": { + "type": "string", + "description": "The resource ID of the document — a unique, internal identifier that Cosmos DB uses to find the document quickly inside its physical storage" + }, + "_self": { + "type": "string", + "description": "A URI path to the document within the Cosmos DB REST API. You can use it to directly operate (read/update/delete) on the document via the API." + }, + "_ts": { + "type": "number", + "description": "The timestamp (in UNIX epoch seconds) of when the document was last modified" + } + }, + "required": [ + "id", + "replenishment_id", + "transaction_date", + "sku_id", + "units", + "vendor_id" + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema new file mode 100644 index 0000000000..b172353823 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema @@ -0,0 +1,5 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema new file mode 100644 index 0000000000..2e5d616a4e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema @@ -0,0 +1,35 @@ +{ + "title": "Return Transactions", + "description": "Flattened Table for all returns", + "type": "object", + "properties": { + "replenishment_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "vendor_id": { + "type": "string", + "description": "Unique identifier for the customer making the return." + }, + "sku_id": { + "type": "string", + "description": "SKU identifier for the returned item." + }, + "units": { + "type": "number", + "description": "Number of units returns." + } + }, + "required": [ + "replenishment_id", + "transaction_date", + "vendor_id", + "sku_id", + "units" + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json new file mode 100644 index 0000000000..fd1cb70752 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json @@ -0,0 +1,12 @@ +{ + "id": "2000", + "return_id": "2000", + "receipt_id": "1000", + "transaction_date": "2025-04-02 10:30:00", + "customer_id": "50001", + "items": [ + {"sku_id": "101", "units": 1.0, "unit_price": 9.99}, + {"sku_id": "201", "units": 1.0, "unit_price": 9.99}, + {"sku_id": "301", "units": 1.0, "unit_price": 9.99} + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema new file mode 100644 index 0000000000..66c44a88c6 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema @@ -0,0 +1,6 @@ +{ + "type": "string", + "title": "Returns Transaction Identifier Key", + "description": "A unique identifier for the returns transaction", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema new file mode 100644 index 0000000000..70f4954615 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema @@ -0,0 +1,66 @@ +{ + "title": "Return Transaction Record Value", + "description": "Schema for a return transaction record, including return ID, receipt ID, transaction date, and a list of returned items.", + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Unique identifier for the return transaction." + }, + "return_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier for the return associated with the transaction." + }, + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier of the original receipt linked to the return." + }, + "transaction_date": { + "type": "string", + "format": "date-time", + "description": "Timestamp of when the return transaction occurred, in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the return." + }, + "items": { + "type": "array", + "description": "List of returned items in the transaction.", + "items": { + "type": "object", + "properties": { + "sku_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "SKU identifier for the returned item." + }, + "units": { + "type": "number", + "description": "Number of units returned." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the returned item." + } + }, + "required": [ + "sku_id", + "units", + "unit_price" + ] + } + } + }, + "required": [ + "id", + "return_id", + "receipt_id", + "transaction_date", + "items", + "customer_id" + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema new file mode 100644 index 0000000000..b172353823 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema @@ -0,0 +1,5 @@ +{ + "type": "string", + "description": "A unique identifier for the product SKU.", + "pattern": "^[0-9]+$" +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema new file mode 100644 index 0000000000..dabf42f1c3 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema @@ -0,0 +1,41 @@ +{ + "title": "Return Transactions", + "description": "Flattened Table for all returns", + "type": "object", + "properties": { + "receipt_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Identifier associated with the transaction receipt." + }, + "transaction_date": { + "type": "string", + "description": "Date and time of the transaction in 'YYYY-MM-DD HH:MM:SS' format." + }, + "customer_id": { + "type": "string", + "description": "Unique identifier for the customer making the return." + }, + "sku_id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "SKU identifier for the returned item." + }, + "units": { + "type": "number", + "description": "Number of units returns." + }, + "unit_price": { + "type": "number", + "description": "Price per unit of the item." + } + }, + "required": [ + "receipt_id", + "transaction_date", + "customer_id", + "sku_id", + "units", + "unit_price" + ] +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md b/073-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md new file mode 100644 index 0000000000..0f01a2b1fa --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md @@ -0,0 +1,126 @@ +# Azure Resource Provisioning + +This guide shows you how to set up the Azure Resources using Terraform + +### 1. **Install Terraform** + +- If you haven’t installed Terraform yet, install it: + + ```bash + # (on MacOS with Homebrew) + + # Configure connection to the repo + brew tap hashicorp/tap + + # Install the latest version of Terraform CLi + brew install hashicorp/tap/terraform + + ``` + or + [Download Terraform manually](https://developer.hashicorp.com/terraform/downloads). + +--- + +### 2. **Authenticate to Azure** + +You must be logged into Azure so Terraform can create the resources for you. + +Run: + +```bash + +az login + +``` +- This will open a browser to authenticate. +- If you have multiple Azure subscriptions, you might also need: + + ```bash + # Display your Azure Subscriptions + az account list + + # Specify the Azure Subscription you are using for the Automation + az account set --subscription "your-subscription-id" + + # Specifiy the Subscription in the Environment Variable for Terraform + ARM_SUBSCRIPTION_ID="your-subscription-id" + ``` + +--- + +### 3. **Initialize Terraform** + +Inside the folder where you have your `main.tf`: + +```bash + +terraform init + +``` +- This downloads the **Azure Provider** and sets up your working directory. + +--- + +### 4. **(Optional) Review What Terraform Will Do** + +See what Terraform *plans* to create: + +```bash + +terraform plan + +``` +- It checks your script and shows you exactly what it will create **without** making changes yet. +- Always a good practice before applying. + +--- + +### 5. **Apply Terraform to Create Resources** + +Now **provision** the resources: + +```bash + +terraform apply + +``` + +- Terraform will show you a detailed list of all resources it will create. +- Type **`yes`** when prompted to approve. + +🌟 After a few minutes, Cosmos DB, Azure AI Search, Storage Account, and Redis Cache will be created in your Azure account! + +--- + +### 6. **Outputs** + +If you included the `output` blocks (like I did in the Terraform file earlier), after `apply`, Terraform will print the important connection details: + +✅ Cosmos DB endpoint +✅ Storage account blob URL +✅ Redis hostname and access key +✅ Azure Search keys + +You can copy this and keep them save for later. These will be needed to provision the Confluent Cloud Resources. + +--- + +### Quick Recap +| Step | Command | +|-------------------|-------------------------------------------| +| Authenticate to Azure | `az login` | +| Initialize Terraform | `terraform init` | +| Plan (Preview) | `terraform plan` | +| Apply (Provision) | `terraform apply` | + +--- + +### **Destroy the resources when you are done ** +If you ever want to delete everything created by the script: + +```bash +terraform destroy +``` +(Also prompts you for confirmation.) + +--- \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh b/073-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh new file mode 100755 index 0000000000..8cf09fe05a --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +API_KEY="GXBNXDHDJ3PQK2ZT" +API_SECRET="GApDfNmd09jMAFzdwedbUZWI3FNM6aOTWe95H0gkN1bXpJuEYsin2hs09jTZne9u" + +# export KAFKA_CLUSTER_ID="lkc-vvwyq0" +# export KAFKA_API_KEY="GXBNXDHDJ3PQK2ZT" +# export KAFKA_API_SECRET="GApDfNmd09jMAFzdwedbUZWI3FNM6aOTWe95H0gkN1bXpJuEYsin2hs09jTZne9u" + +curl -u "${API_KEY}:${API_SECRET}" \ + https://api.confluent.cloud/connect/v1/environments diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh b/073-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh new file mode 100755 index 0000000000..a81f407f3e --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Generate a local env.sh file from terraform output + +# Exit immediately if a command exits with a non-zero status +set -e + +# Where to output the env file +ENV_FILE="./azure_environment_variables.sh" + +# Generate the env.sh file +echo "#!/bin/bash" > "$ENV_FILE" +echo "" >> "$ENV_FILE" + +# Read outputs and write them as export statements + +echo "# Azure Resource Group for Resources" >> "$ENV_FILE" +terraform output -raw resource_group_name | awk '{print "export AZURE_RESOURCE_GROUP=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +echo "# Azure Cosmos DB Credentials" >> "$ENV_FILE" +terraform output -raw cosmosdb_account_name | awk '{print "export AZURE_COSMOS_DB_ACCOUNT_NAME=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw cosmosdb_primary_key | awk '{print "export AZURE_COSMOS_DB_ACCOUNT_KEY=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw cosmosdb_database_name | awk '{print "export AZURE_COSMOS_DB_DATABASE_NAME=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +echo "# Azure AI Search Credentials" >> "$ENV_FILE" +terraform output -raw search_service_name | awk '{print "export AZURE_SEARCH_SERVICE_NAME=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw azure_search_admin_key | awk '{print "export AZURE_SEARCH_API_KEY=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +echo "# Azure Storage Account Credentials" >> "$ENV_FILE" +terraform output -raw storage_account_name | awk '{print "export AZURE_STORAGE_ACCOUNT_NAME=\"" $0 "\""}' >> "$ENV_FILE" +terraform output -raw storage_account_primary_access_key | awk '{print "export AZURE_STORAGE_ACCOUNT_KEY=\"" $0 "\""}' >> "$ENV_FILE" +echo "" >> "$ENV_FILE" + +#echo "# Azure Redis Cache Credentials" >> "$ENV_FILE" +#terraform output -raw redis_hostname | awk '{print "export REDIS_HOSTNAME=\"" $0 "\""}' >> "$ENV_FILE" +#terraform output -raw redis_primary_access_key | awk '{print "export REDIS_PRIMARY_ACCESS_KEY=\"" $0 "\""}' >> "$ENV_FILE" +#echo "" >> "$ENV_FILE" + +echo "✅ Environment file generated: $ENV_FILE" diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf new file mode 100644 index 0000000000..c31aef6c6b --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf @@ -0,0 +1,148 @@ + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "4.37.0" + } + + confluent = { + source = "confluentinc/confluent" + version = "2.35.0" + } + + random = { + source = "hashicorp/random" + version = "3.7.2" + } + } + + required_version = ">= 1.12.2" +} + +provider "random" { + # Random provider configuration + # This can be left empty or configured as needed +} + +provider "azurerm" { + features {} + subscription_id = var.azure_subscription_id + storage_use_azuread = true +} + +provider "confluent" { + kafka_id = var.kafka_id # optionally use KAFKA_ID env var + kafka_rest_endpoint = var.kafka_rest_endpoint # optionally use KAFKA_REST_ENDPOINT env var + kafka_api_key = var.kafka_api_key # optionally use KAFKA_API_KEY env var + kafka_api_secret = var.kafka_api_secret # optionally use KAFKA_API_SECRET env var + + flink_api_key = var.flink_api_key # optionally use FLINK_API_KEY env var + flink_api_secret = var.flink_api_secret # optionally use FLINK_API_SECRET env var + flink_rest_endpoint = var.flink_rest_endpoint # optionally use FLINK_REST_ENDPOINT env var + flink_compute_pool_id = var.flink_compute_pool_id # optionally use FLINK_COMPUTE_POOL_ID env var + flink_principal_id = var.flink_principal_id # optionally use FLINK_PRINCIPAL_ID + organization_id = var.confluent_organization_id # optionally use ORGANIZATION_ID env var + environment_id = var.confluent_environment_id # optionally use ENVIRONMENT_ID env var + + schema_registry_id = var.schema_registry_id # optionally use SCHEMA_REGISTRY_ID env var + schema_registry_rest_endpoint = var.schema_registry_rest_endpoint # optionally use SCHEMA_REGISTRY_REST_ENDPOINT env var + schema_registry_api_key = var.schema_registry_api_key # optionally use SCHEMA_REGISTRY_API_KEY env var + schema_registry_api_secret = var.schema_registry_api_secret # optionally use SCHEMA_REGISTRY_API_SECRET env var + + # Confluent Cloud API (for managing connectors and environments) + cloud_api_key = var.cloud_api_key + cloud_api_secret = var.cloud_api_secret +} + +# New variables for merged changes +variable "cloud_api_key" { type = string } +variable "cloud_api_secret" { type = string } + +# ----------------- +# Core Confluent IDs / Endpoints +# ----------------- +variable "kafka_id" { type = string } +variable "kafka_rest_endpoint" { type = string } +variable "kafka_api_key" { type = string } +variable "kafka_api_secret" { type = string } +variable "flink_api_key" { type = string } +variable "flink_api_secret" { type = string } +variable "flink_rest_endpoint" { type = string } +variable "flink_compute_pool_id" { type = string } +variable "flink_principal_id" { type = string } +variable "confluent_organization_id" { type = string } +variable "confluent_environment_id" { type = string } +variable "schema_registry_id" { type = string } +variable "schema_registry_rest_endpoint" { type = string } +variable "schema_registry_api_key" { type = string } +variable "schema_registry_api_secret" { type = string } +variable "name_prefix" { + description = "Prefix for all resource names" + type = string + + validation { + condition = length(var.name_prefix) <= 6 && can(regex("^[a-z0-9]+$", var.name_prefix)) + error_message = "The name_prefix must be 6 characters or fewer and contain only lowercase letters (a-z) or numbers (0-9)." + } +} + +# ----------------- +# Azure variables +# ----------------- +variable "resource_group_location" { + type = string + default = "eastus2" +} +variable "azure_subscription_id" { type = string } + +/* +# Service Principal (for Azure Search connector) - supply if using AI Search connectors +variable "service_principal_tenant_id" { type = string } +variable "service_principal_subscription_id" { type = string } +variable "service_principal_client_id" { type = string } +variable "service_principal_client_secret" { type = string } +*/ + + +# ----------------- +# Kafka topic configuration +# ----------------- +variable "kafka_partitions_count" { + type = number + default = 6 +} + +# ----------------- +# Connector Maps +# ----------------- +variable "blob_store_connectors" { + description = "Blob source connectors map" + type = map(object({ + name = string + topic = string + container = string + })) + default = {} +} + + + +variable "cosmos_db_connectors" { + description = "Cosmos DB source connectors map" + type = map(object({ + name = string + topic = string + })) + default = {} +} + +variable "ai_search_connectors" { + description = "Azure AI Search sink connectors map" + type = map(object({ + name = string + topic = string + index = string + })) + default = {} +} diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf new file mode 100644 index 0000000000..e56b2b5828 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf @@ -0,0 +1,167 @@ +# Resource Group +resource "azurerm_resource_group" "main" { + name = "${var.name_prefix}-confluentwth-rg" + location = var.resource_group_location +} + + + +resource "azurerm_storage_account" "storage" { + name = "${var.name_prefix}sa" + resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.main.location + account_tier = "Standard" + account_replication_type = "ZRS" + account_kind = "StorageV2" + public_network_access_enabled = true + shared_access_key_enabled = true +} + +# Define a list of blob container names +locals { + container_names = [ + "departments", + "product-pricing", + "product-skus" + ] +} + +# Create containers using a loop +resource "azurerm_storage_container" "containers" { + for_each = toset(local.container_names) + name = each.value + storage_account_id = azurerm_storage_account.storage.id + container_access_type = "private" +} + +# Azure AI Search Instance +# New changes to the Azure Search Service API require the use of +# `local_authentication_enabled` and `authentication_failure_mode` properties. +# These properties are required to enable local authentication and set the failure mode. +# The `public_network_access_enabled` property is also set to true to allow public access. +# https://learn.microsoft.com/en-us/azure/search/search-security-enable-roles?tabs=config-svc-rest%2Cdisable-keys-cli +# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/search_service +resource "azurerm_search_service" "search" { + name = "${var.name_prefix}-search" + resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.main.location + sku = "standard" + partition_count = 1 + replica_count = 1 + local_authentication_enabled = true + authentication_failure_mode = "http403" + public_network_access_enabled = true + + depends_on = [ azurerm_storage_container.containers ] +} + +# Azure Cosmos DB (SQL API) +resource "azurerm_cosmosdb_account" "cosmosdb" { + name = "${var.name_prefix}cosmos" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + offer_type = "Standard" + kind = "GlobalDocumentDB" + public_network_access_enabled = true + local_authentication_disabled = false + + + consistency_policy { + consistency_level = "Strong" + } + + geo_location { + location = azurerm_resource_group.main.location + failover_priority = 0 + } + + depends_on = [ azurerm_storage_container.containers ] +} + +# Cosmos DB SQL Database +resource "azurerm_cosmosdb_sql_database" "retailstore" { + name = "retailstore" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + + throughput = 400 # Provisioned throughput at the database level (optional if you want) +} + +# Purchases Container +resource "azurerm_cosmosdb_sql_container" "purchases" { + name = "purchases" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/customer_id"] + throughput = 400 # optional: you can set throughput here too, or rely on database throughput +} + +# Returns Container +resource "azurerm_cosmosdb_sql_container" "returns" { + name = "returns" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/customer_id"] + throughput = 400 +} + +# Replenishments Container +resource "azurerm_cosmosdb_sql_container" "replenishments" { + name = "replenishments" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/vendor_id"] + throughput = 400 +} + +# Azure Redis Cache +resource "azurerm_redis_cache" "redis" { + name = "${var.name_prefix}redis" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + capacity = 1 + family = "C" + sku_name = "Standard" + non_ssl_port_enabled = false + minimum_tls_version = "1.2" + public_network_access_enabled = true + redis_version = "6" + shard_count = 0 + + redis_configuration { + active_directory_authentication_enabled = true + aof_backup_enabled = false + authentication_enabled = true + maxfragmentationmemory_reserved = 125 + maxmemory_delta = 125 + maxmemory_reserved = 125 + notify_keyspace_events = "" + } +} + +# Azure AI Services (AI Foundry) +resource "azurerm_ai_services" "ai_services" { + name = "${var.name_prefix}aiservices" + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + sku_name = "S0" + custom_subdomain_name = "${var.name_prefix}models" + + local_authentication_enabled = true + public_network_access = "Enabled" + outbound_network_access_restricted = false + + identity { + type = "SystemAssigned" + } + + network_acls { + default_action = "Allow" + } +} \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf new file mode 100644 index 0000000000..3aa2aa5866 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf @@ -0,0 +1,264 @@ + +# Define a list of Kafka topic names +locals { + kafka_topic_names = [ + "departments", + "departments_flat", + "product_pricing", + "product_skus", + "purchases", + "replenishments", + "returns", + "net_sales", # need to drop this because we now use net_sales_depot + "product_inventory" # need to drop this because we now use product_inventory_depot + ] + + kafka_topic_key_names = [ + "purchases", + "replenishments", + "returns", + "net_sales", # need to drop this because we now use net_sales_depot + "product_inventory" # need to drop this because we now use product_inventory_depot + ] +} + +# New variables for service account auth and Cosmos DB sink connectors +variable "kafka_service_account_id" { + description = "Kafka Service Account ID for connector authentication" + type = string +} + +#variable "cosmos_db_sink_connectors" { +# description = "Map of Cosmos DB sink connectors configuration" +# type = map(object({ +# name = string +# topic = string +# container_mapping = string +# })) +#} + +resource "confluent_schema_registry_cluster_config" "microsoft_hackathon" { + compatibility_level = "NONE" + + lifecycle { + prevent_destroy = false + } +} + +# Create the Retail Store Kafka Topics +resource "confluent_kafka_topic" "topics" { + for_each = toset(local.kafka_topic_names) + topic_name = each.value + partitions_count = var.kafka_partitions_count + + depends_on = [ + confluent_schema_registry_cluster_config.microsoft_hackathon + ] + + lifecycle { + prevent_destroy = false + } +} + +# Create the Schema Registry Entries for each Topic Key +resource "confluent_schema" "key_schemas" { + for_each = toset(local.kafka_topic_key_names) + subject_name = "${each.value}-key" + format = "JSON" + schema = file("../retail_store/${each.value}/schemas/${each.value}-key.schema") + hard_delete = true # Optional: Set to true if you want to hard delete the schema + + depends_on = [ confluent_schema_registry_cluster_config.microsoft_hackathon ] +} + +# Create the Schema Registry Entries for each Topic Value +resource "confluent_schema" "value_schemas" { + for_each = toset(local.kafka_topic_names) + subject_name = "${each.value}-value" + format = "JSON" + schema = file("../retail_store/${each.value}/schemas/${each.value}-value.schema") + hard_delete = true # Optional: Set to true if you want to hard delete the schema + depends_on = [ confluent_schema_registry_cluster_config.microsoft_hackathon ] +} + +# Create the Source Connectors for Azure Blob Storage +resource "confluent_connector" "blob_store_connectors" { + + for_each = var.blob_store_connectors + + environment { + id = var.confluent_environment_id + } + + kafka_cluster { + id = var.kafka_id + } + + config_sensitive = { + "azblob.account.key" = azurerm_storage_account.storage.primary_access_key + } + + config_nonsensitive = { + "azblob.account.name" = azurerm_storage_account.storage.name + "connector.class" = "AzureBlobSource" + "name" = each.value.name + "topic.regex.list" = each.value.topic + "schema.context.name" = "default" + "kafka.auth.mode" = "SERVICE_ACCOUNT" + "kafka.service.account.id" = var.kafka_service_account_id + "azblob.container.name" = each.value.container + "azblob.retry.type" = "EXPONENTIAL" + "input.data.format" = "JSON" + "output.data.format" = "JSON" + "topics.dir" = "topics" + "directory.delim" = "/" + "behavior.on.error" = "FAIL" + "format.bytearray.separator" = "\n" + "task.batch.size" = "10" + "file.discovery.starting.timestamp" = "0" + "azblob.poll.interval.ms" = "60000" + "record.batch.max.size" = "200" + "tasks.max" = "1" + "value.converter.decimal.format" = "BASE64" + "value.converter.replace.null.with.default" = "true" + "value.converter.reference.subject.name.strategy" = "DefaultReferenceSubjectNameStrategy" + "value.converter.schemas.enable" = "false" + "errors.tolerance" = "none" + "value.converter.value.subject.name.strategy" = "TopicNameStrategy" + "key.converter.key.subject.name.strategy" = "TopicNameStrategy" + "value.converter.ignore.default.for.nullables" = "false" + "auto.restart.on.user.error" = "true" + } + + depends_on = [ + azurerm_storage_account.storage, + azurerm_storage_container.containers, + confluent_kafka_topic.topics, + confluent_schema.key_schemas, + confluent_schema.value_schemas + ] + + lifecycle { + prevent_destroy = false + } +} + + +# Create the Source Connectors for Azure Cosmos DB +resource "confluent_connector" "cosmos_db_connectors" { + for_each = var.cosmos_db_connectors + + environment { + id = var.confluent_environment_id + } + + kafka_cluster { + id = var.kafka_id + } + + config_sensitive = { + # Using master key as sensitive (if source connector requires writes for offset mgmt) + "connect.cosmos.master.key" = azurerm_cosmosdb_account.cosmosdb.primary_key + } + + config_nonsensitive = { + "connect.cosmos.connection.endpoint" = "https://${azurerm_cosmosdb_account.cosmosdb.name}.documents.azure.com:443/" + "connect.cosmos.databasename" = azurerm_cosmosdb_sql_database.retailstore.name + "connector.class" = "CosmosDbSource" + "name" = each.value.name + "schema.context.name" = "default" + "kafka.auth.mode" = "SERVICE_ACCOUNT" + "kafka.service.account.id" = var.kafka_service_account_id + "connect.cosmos.containers.topicmap" = each.value.topic + "connect.cosmos.task.timeout" = "5000" + "connect.cosmos.task.buffer.size" = "10000" + "connect.cosmos.task.batch.size" = "100" + "connect.cosmos.task.poll.interval" = "1000" + "output.data.format" = "JSON_SR" + "connect.cosmos.messagekey.enabled" = "true" + "connect.cosmos.messagekey.field" = "id" + "tasks.max" = "1" + "auto.restart.on.user.error" = "true" + "value.converter.decimal.format" = "BASE64" + "value.converter.reference.subject.name.strategy" = "DefaultReferenceSubjectNameStrategy" + "value.converter.value.subject.name.strategy" = "TopicNameStrategy" + "key.converter.key.subject.name.strategy" = "TopicNameStrategy" + } + + depends_on = [ + azurerm_cosmosdb_account.cosmosdb, + azurerm_cosmosdb_sql_database.retailstore, + azurerm_cosmosdb_sql_container.purchases, + azurerm_cosmosdb_sql_container.returns, + azurerm_cosmosdb_sql_container.replenishments, + confluent_kafka_topic.topics, + confluent_schema.key_schemas, + confluent_schema.value_schemas + ] + + lifecycle { + prevent_destroy = false + } +} + +# Create the Source Connectors for Azure AI Search +resource "confluent_connector" "ai_search_connectors" { + for_each = var.ai_search_connectors + + environment { + id = var.confluent_environment_id + } + + kafka_cluster { + id = var.kafka_id + } + + config_sensitive = { + # API key for Azure Search and client secret treated as sensitive + "azure.search.api.key" = azurerm_search_service.search.primary_key + "azure.search.client.secret" = var.service_principal_client_secret + } + + config_nonsensitive = { + "azure.search.resourcegroup.name" = var.resource_group_name + "azure.search.service.name" = azurerm_search_service.search.name + "azure.search.tenant.id" = var.service_principal_tenant_id + "azure.search.subscription.id" = var.service_principal_subscription_id + "azure.search.client.id" = var.service_principal_client_id + "index.name" = each.value.index + "topics" = each.value.topic + "schema.context.name" = "default" + "input.data.format" = "JSON_SR" + "connector.class" = "AzureCognitiveSearchSink" + "name" = each.value.name + "kafka.auth.mode" = "SERVICE_ACCOUNT" + "kafka.service.account.id" = var.kafka_service_account_id + "write.method" = "Upload" + "delete.enabled" = "true" + "key.mode" = "KEY" + "max.batch.size" = "25" + "max.retry.ms" = "300000" + "max.poll.interval.ms" = "300000" + "max.poll.records" = "500" + "tasks.max" = "1" + "auto.restart.on.user.error" = "true" + "value.converter.decimal.format" = "BASE64" + "value.converter.reference.subject.name.strategy" = "DefaultReferenceSubjectNameStrategy" + "value.converter.value.subject.name.strategy" = "TopicNameStrategy" + "key.converter.key.subject.name.strategy" = "TopicNameStrategy" + "transforms" = "sku_id_to_key" + "transforms.sku_id_to_key.type" = "org.apache.kafka.connect.transforms.ValueToKey" + "transforms.sku_id_to_key.fields" = "sku_id" + } + + depends_on = [ + azurerm_search_service.search, + confluent_kafka_topic.topics, + confluent_schema.key_schemas, + confluent_schema.value_schemas + ] + + lifecycle { + prevent_destroy = false + } +} diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf new file mode 100644 index 0000000000..8de801902d --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf @@ -0,0 +1,67 @@ +# Outputs (Used Later for Setting Up Confluent Resources) +output "resource_group_name" { + description = "The name of the resource group" + value = azurerm_resource_group.main.name +} + +output "cosmosdb_endpoint" { + description = "Endpoint URI for CosmosDB Account" + value = azurerm_cosmosdb_account.cosmosdb.endpoint +} + +output "cosmosdb_account_name" { + description = "The name of the Cosmos DB account" + value = azurerm_cosmosdb_account.cosmosdb.name +} + +output "cosmosdb_primary_key" { + description = "Primary key for CosmosDB Account" + value = azurerm_cosmosdb_account.cosmosdb.primary_key + sensitive = true +} + +output "cosmosdb_database_name" { + description = "The name of the Cosmos DB SQL database" + value = azurerm_cosmosdb_sql_database.retailstore.name +} + +output "search_service_name" { + description = "The name of the Azure AI Search instance" + value = azurerm_search_service.search.name +} + +output "azure_search_admin_key" { + description = "Primary Admin Key for Azure AI Search" + value = azurerm_search_service.search.primary_key + sensitive = true +} + +output "azure_search_query_key" { + description = "Primary Query Key for Azure AI Search" + value = azurerm_search_service.search.query_keys[0].key + sensitive = true +} + +output "azure_search_endpoint" { + description = "Endpoint URI for Azure AI Search" + value = azurerm_search_service.search.name +} + +output "storage_account_name" { + description = "The name of the storage account" + value = azurerm_storage_account.storage.name +} + +output "storage_account_primary_access_key" { + description = "Primary Access Key for Azure Storage Account" + value = azurerm_storage_account.storage.primary_access_key + sensitive = true +} + +output "storage_account_blob_endpoint" { + description = "Blob service endpoint for the storage account" + value = azurerm_storage_account.storage.primary_blob_endpoint +} + + + diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh b/073-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh new file mode 100755 index 0000000000..9539a52d33 --- /dev/null +++ b/073-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + + +echo "Cleaning up Terraform resources..." + +# Remove Terraform state files and directories +rm -vrf .terraform* +rm -vrf .terraform.lock.hcl +rm -vrf terraform.tfstate +rm -vrf terraform.tfstate.backup +rm -vrf *.tfplan + +echo "Terraform resources cleaned up successfully." From 5b26e3925e55075a50ed4f899b54187eab0ec0b3 Mon Sep 17 00:00:00 2001 From: Israel Ekpo <isekpo@microsoft.com> Date: Fri, 17 Oct 2025 14:48:24 -0400 Subject: [PATCH 16/32] saving changes --- .../Coach/Lectures.pptx | Bin 196287 -> 0 bytes xxx-AIWithConfluentOnAzure/Coach/README.md | 79 -------------- .../Coach/Solution-00.md | 20 ---- .../Coach/Solution-01.md | 20 ---- .../Coach/Solution-02.md | 20 ---- .../Coach/Solution-03.md | 20 ---- .../Coach/Solution-04.md | 20 ---- .../Coach/Solution-05.md | 20 ---- .../Coach/Solutions/.gitkeep | 0 xxx-AIWithConfluentOnAzure/README.md | 51 --------- .../Student/Challenge-00.md | 100 ------------------ .../Student/Challenge-01.md | 54 ---------- .../Student/Challenge-02.md | 59 ----------- .../Student/Challenge-03.md | 80 -------------- .../Student/Challenge-04.md | 73 ------------- .../Student/Challenge-05.md | 78 -------------- .../Student/Resources/.gitkeep | 0 17 files changed, 694 deletions(-) delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Lectures.pptx delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/README.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-00.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-01.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-02.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-03.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-04.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solution-05.md delete mode 100644 xxx-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep delete mode 100644 xxx-AIWithConfluentOnAzure/README.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-00.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-01.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-02.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-03.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-04.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Challenge-05.md delete mode 100644 xxx-AIWithConfluentOnAzure/Student/Resources/.gitkeep diff --git a/xxx-AIWithConfluentOnAzure/Coach/Lectures.pptx b/xxx-AIWithConfluentOnAzure/Coach/Lectures.pptx deleted file mode 100644 index 34cfe52f45a056e33791ebf176cee017e41362e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196287 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�_IWyNZZ9mNx0@56UmNEa+jb*vV<xCX}_D@Tf6 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%0A2O;OS!shB_ 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 z%0A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 J40sEG@;^hlltKUi diff --git a/xxx-AIWithConfluentOnAzure/Coach/README.md b/xxx-AIWithConfluentOnAzure/Coach/README.md deleted file mode 100644 index aa8938734d..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# What The Hack - AIWithConfluentOnAzure - Coach Guide - -## Introduction - -Welcome to the coach's guide for the AIWithConfluentOnAzure What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. - -This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. - -**NOTE:** If you are a Hackathon participant, this is the answer guide. Don't cheat yourself by looking at these during the hack! Go learn something. :) - -## Coach's Guides - -- Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** - - Prepare your workstation to work with Azure. -- Challenge 01: **[Title of Challenge](./Solution-01.md)** - - Description of challenge -- Challenge 02: **[Title of Challenge](./Solution-02.md)** - - Description of challenge -- Challenge 03: **[Title of Challenge](./Solution-03.md)** - - Description of challenge -- Challenge 04: **[Title of Challenge](./Solution-04.md)** - - Description of challenge -- Challenge 05: **[Title of Challenge](./Solution-05.md)** - - Description of challenge - -## Coach Prerequisites - -This hack has pre-reqs that a coach is responsible for understanding and/or setting up BEFORE hosting an event. Please review the [What The Hack Hosting Guide](https://aka.ms/wthhost) for information on how to host a hack event. - -The guide covers the common preparation steps a coach needs to do before any What The Hack event, including how to properly configure Microsoft Teams. - -### Student Resources - -Before the hack, it is the Coach's responsibility to download and package up the contents of the `/Student/Resources` folder of this hack into a "Resources.zip" file. The coach should then provide a copy of the Resources.zip file to all students at the start of the hack. - -Always refer students to the [What The Hack website](https://aka.ms/wth) for the student guide: [https://aka.ms/wth](https://aka.ms/wth) - -**NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. - -### Additional Coach Prerequisites (Optional) - -_Please list any additional pre-event setup steps a coach would be required to set up such as, creating or hosting a shared dataset, or deploying a lab environment._ - -## Azure Requirements - -This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. - -_Please list Azure subscription requirements._ - -_For example:_ - -- Azure resources that will be consumed by a student implementing the hack's challenges -- Azure permissions required by a student to complete the hack's challenges. - -## Suggested Hack Agenda (Optional) - -_This section is optional. You may wish to provide an estimate of how long each challenge should take for an average squad of students to complete and/or a proposal of how many challenges a coach should structure each session for a multi-session hack event. For example:_ - -- Sample Day 1 - - Challenge 1 (1 hour) - - Challenge 2 (30 mins) - - Challenge 3 (2 hours) -- Sample Day 2 - - Challenge 4 (45 mins) - - Challenge 5 (1 hour) - - Challenge 6 (45 mins) - -## Repository Contents - -_The default files & folders are listed below. You may add to this if you want to specify what is in additional sub-folders you may add._ - -- `./Coach` - - Coach's Guide and related files -- `./Coach/Solutions` - - Solution files with completed example answers to a challenge -- `./Student` - - Student's Challenge Guide -- `./Student/Resources` - - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-00.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-00.md deleted file mode 100644 index 8ca1a44d71..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/Solution-00.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 00 - <Title of Challenge> - Coach's Guide - -**[Home](./README.md)** - [Next Solution >](./Solution-01.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-01.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-01.md deleted file mode 100644 index 01d1e30c27..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/Solution-01.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 01 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-02.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-02.md deleted file mode 100644 index 1ef8ca5035..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/Solution-02.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 02 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-03.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-03.md deleted file mode 100644 index 9591196509..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/Solution-03.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 03 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-04.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-04.md deleted file mode 100644 index 90a770fdb3..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/Solution-04.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 04 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solution-05.md b/xxx-AIWithConfluentOnAzure/Coach/Solution-05.md deleted file mode 100644 index c320bf9745..0000000000 --- a/xxx-AIWithConfluentOnAzure/Coach/Solution-05.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 05 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-04.md) - **[Home](./README.md)** - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/xxx-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep b/xxx-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/xxx-AIWithConfluentOnAzure/README.md b/xxx-AIWithConfluentOnAzure/README.md deleted file mode 100644 index f693803823..0000000000 --- a/xxx-AIWithConfluentOnAzure/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# What The Hack - AI With Confluent On Azure - -## Introduction - -This hackathon immerses you in building a real-time AI agent using **Confluent Cloud on Microsoft Azure**. You’ll learn how Confluent’s data streaming platform—based on Apache Kafka—can connect and process retail data in real time, enabling AI-driven insights that keep pace with constantly changing business conditions [1][2]. Whether it’s ingesting product SKUs or synchronizing inventory levels, Confluent Cloud on Azure offers a unified, scalable, and secure platform to design near real-time pipelines and deliver accurate, intelligent solutions. - -Throughout this hack, you’ll capture data from diverse sources—such as transaction logs, returns, and purchase records—and then transform or enrich that data using Apache Flink or ksqlDB. The result is an always up-to-date data backbone, ready to power AI-driven applications that swiftly respond to customer needs, supplier demands, and dynamic inventory scenarios [3][4]. - - -## Learning Objectives - -By completing this hack, you will: - -- **Set up a real-time streaming environment** on Confluent Cloud in Azure, incorporating best practices for scalability, reliability, and security. -- **Ingest and process diverse data sources** using Apache Kafka, exploring how pre-built Confluent connectors facilitate end-to-end data pipelines. -- **Apply basic stream processing** through ksqlDB or Apache Flink to merge, filter, or aggregate event data in real time. -- **Sync transformed data to Azure services** like Cosmos DB or Azure AI Search, ensuring your AI agent always has a near real-time view of retail operations. -- **Lay the groundwork for AI-driven decision-making**, demonstrating how real-time data improves accuracy and responsiveness for both customers and internal stakeholders. - -## Challenges - -- Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** - - Prepare your workstation to work with Azure. -- Challenge 01: **[Configuration of Agentic Resources and Deployment of Backend](Student/Challenge-01.md)** - - Description of challenge -- Challenge 02: **[Configuration of Chat Interface and Frontend](Student/Challenge-02.md)** - - Description of challenge -- Challenge 03: **[Simulation of Employee - Reports, Status etc](Student/Challenge-03.md)** - - Description of challenge -- Challenge 04: **[Simulation of Suppliers - Replenishments](Student/Challenge-04.md)** - - Description of challenge -- Challenge 05: **[Simulation of Customers - Purchases and Returns](Student/Challenge-05.md)** - - Description of challenge - -## Prerequisites - -- Your own Azure subscription with Owner access -- Visual Studio Code -- Azure CLI - -## References -- 1 https://www.confluent.io/apache-kafka-vs-confluent/ -- 2 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/overview -- 3 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create -- 4 https://www.confluent.io/hub/ - -## Contributors - -- Andy Huang -- Israel Ekpo -- Juan Llovet de Casso diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-00.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-00.md deleted file mode 100644 index 61aa89aa4b..0000000000 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-00.md +++ /dev/null @@ -1,100 +0,0 @@ -# Challenge 00 - Prerequisites - Ready, Set, GO! - -**[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) - -**_This is a template for "Challenge Zero" which focuses on getting prerequisites set up for the hack. The italicized text provides hints & examples of what should or should NOT go in each section._** - -**_We have included links to some common What The Hack pre-reqs in this template. All common prerequisite links go to the WTH-CommonPrerequisites page where there are more details on what each tool's purpose is._** - -**_You should remove any common pre-reqs that are not required for your hack. Then add additional pre-reqs that are required for your hack in the Description section below._** - -**_You should remove all italicized & sample text in this template and replace with your content._** - -## Introduction - -Thank you for participating in the AIWithConfluentOnAzure What The Hack. Before you can hack, you will need to set up some prerequisites. - -## Common Prerequisites - -We have compiled a list of common tools and software that will come in handy to complete most What The Hack Azure-based hacks! - -You might not need all of them for the hack you are participating in. However, if you work with Azure on a regular basis, these are all things you should consider having in your toolbox. - -<!-- If you are editing this template manually, be aware that these links are only designed to work if this Markdown file is in the /xxx-HackName/Student/ folder of your hack. --> - -- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) -- [Windows Subsystem for Linux](../../000-HowToHack/WTH-Common-Prerequisites.md#windows-subsystem-for-linux) -- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) - - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) - - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) - - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) - - [Azure PowerShell CmdLets](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-powershell-cmdlets) - - [Azure Cloud Shell](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cloud-shell) -- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) - - [VS Code plugin for ARM Templates](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code-plugins-for-arm-templates) -- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) - -## Description - -_This section should clearly state any additional prerequisite tools that need to be installed or set up in the Azure environment that the student will hack in._ - -_While ordered lists are generally not welcome in What The Hack challenge descriptions, you can use one here in Challenge Zero IF and only IF the steps you are asking the student to perform are not core to the learning objectives of the hack._ - -_For example, if the hack is on IoT Devices and you want the student to deploy an ARM/Bicep template that sets up the environment they will hack in without them needing to understand how ARM/Bicep templates work, you can provide step-by-step instructions on how to deploy the ARM/Bicep template._ - -_Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack. You should leave the sample text below in that refers to the Resources.zip file._ - -**\*NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resources.zip file provided by the coach.\* - -**\*NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.\* - -_Sample challenge zero text for the IoT Hack Of The Century:_ - -Now that you have the common pre-requisites installed on your workstation, there are prerequisites specifc to this hack. - -Your coach will provide you with a Resources.zip file that contains resources you will need to complete the hack. If you plan to work locally, you should unpack it on your workstation. If you plan to use the Azure Cloud Shell, you should upload it to the Cloud Shell and unpack it there. - -Please install these additional tools: - -- [Azure IoT Tools](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools) extension for Visual Studio Code -- .NET SDK 6.0 or later installed on your development machine. This can be downloaded from [here](https://www.microsoft.com/net/download/all) for multiple platforms. - -In the `/Challenge00/` folder of the Resources.zip file, you will find an ARM template, `setupIoTEnvironment.json` that sets up the initial hack environment in Azure you will work with in subsequent challenges. - -Please deploy the template by running the following Azure CLI commands from the location of the template file: -``` -az group create --name myIoT-rg --location eastus -az group deployment create -g myIoT-rg --name HackEnvironment -f setupIoTEnvironment.json -``` - -## Success Criteria - -_Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach._ - -_The success criteria should not be a list of instructions._ - -_Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."_ - -_Sample success criteria for the IoT prerequisites challenge:_ - -To complete this challenge successfully, you should be able to: - -- Verify that you have a bash shell with the Azure CLI available. -- Verify that the ARM template has deployed the following resources in Azure: - - Azure IoT Hub - - Virtual Network - - Jumpbox VM - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -_Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario._ - -**\*Note:** Use descriptive text for each link instead of just URLs.\* - -_Sample IoT resource links:_ - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md deleted file mode 100644 index 65ccfa2826..0000000000 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-01.md +++ /dev/null @@ -1,54 +0,0 @@ -# Challenge 01 - Configuration of Agentic Resources and Deployment of Backend - -[< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) - -## Introduction - -In this challenge, you'll focus on deploying the backend API that will serve as the foundation for your real-time AI agent. This API will eventually consume data streamed through Confluent Cloud on Azure and surface intelligent responses based on the latest available information. - -## Description - -*Need to Update once we confirm architecture* - - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that your Azure resources and API have been deployed -- Verify that the API is reachable and responsive. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* - -*This section is optional and may be omitted.* - -*Sample IoT advanced challenges:* - -Too comfortable? Eager to do more? Try these additional challenges! - -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md deleted file mode 100644 index 6a5379954e..0000000000 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-02.md +++ /dev/null @@ -1,59 +0,0 @@ -# Challenge 02 - Configuration of Chat Interface and Frontend - -[< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) - - -## Pre-requisites - -You must complete **Challenge 01** before starting this challenge. The backend API must be successfully deployed and reachable, as the frontend will depend on it for communication and functionality. - -## Introduction - -In this challenge, you'll configure and deploy the frontend user interface that interacts with your backend API. This frontend UI will allow users to send and receive messages to the AI agent powered by real-time streaming data from Confluent Cloud. **Need to update as I am just filling in generic verbiage** - - -## Description - -**Need to Update as we get details of infrastructure. - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that your frontend and related Azure resources have been deployed. -- Verify that the frontend can communicate with the backend API and receive a valid response. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* - -*This section is optional and may be omitted.* - -*Sample IoT advanced challenges:* - -Too comfortable? Eager to do more? Try these additional challenges! - -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md deleted file mode 100644 index 539e22e5a1..0000000000 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-03.md +++ /dev/null @@ -1,80 +0,0 @@ -# Challenge 03 - Simulation of Employee Persona - -[< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) - - -## Pre-requisites - -You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend interface must be fully deployed and functional, as this challenge builds on top of the running application infrastructure. - - -## Introduction - -In this challenge, you'll simulate the experience of an employee interacting with the AI agent to perform various business-critical operations. This persona has access to operational data such as purchases, returns, and inventory, and can also perform updates to the product catalog in near real time. - -The goal of this challenge is to observe how changes initiated through the agent are processed and reflected across systems in near real time using Confluent Cloud on Azure. These updates—whether querying data or modifying records—flow through Kafka topics, are processed via stream processors like Flink or ksqlDB, and are reflected in the destination datastore with minimal delay. - - -## Description - -In this challenge, you will authenticate as an employee and issue commands to the AI agent to retrieve and update retail operations data. These interactions are routed through the backend API, processed via Confluent Cloud's real-time data infrastructure, and ultimately reflected in the destination datastore. - -- Authenticate using an employee ID and 4-digit PIN. -- Retrieve summaries for a specific date: - - Total purchases - - Total replenishments - - Total returns - - Net sales (purchases - returns) -- Query current inventory level of a specific SKU. -- Modify inventory-related data: - - Change the maximum inventory level of a specific SKU. - - Update the unit price of a specific SKU. - - Add a new SKU to the product catalog. - - Modify the list of SKUs a vendor is authorized to replenish. - -All modifications should propagate through Confluent Cloud and be reflected in the destination data store (e.g., Cosmos DB or Azure AI Search) in near real time. - - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that employee users can authenticate using ID and PIN. -- Show at least three successful read operations. -- Show at least two successful write operations. -- Verify that data changes propagate through Confluent Cloud and are reflected in the destination data store in near real time. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* - -*This section is optional and may be omitted.* - -*Sample IoT advanced challenges:* - -Too comfortable? Eager to do more? Try these additional challenges! - -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md deleted file mode 100644 index f225b41ef7..0000000000 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-04.md +++ /dev/null @@ -1,73 +0,0 @@ -# Challenge 04 - Simulation of Suppliers - Replenishments - -[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) - - -## Pre-requisites - -You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend, frontend, and employee data operations must be functional to ensure supplier-related workflows integrate with the rest of the system. - - -## Introduction - -In this challenge, you’ll take on the role of a vendor or supplier interacting with the AI agent to monitor and replenish inventory levels. These interactions are authorized and scoped to SKUs each vendor is allowed to manage. - -The goal of this challenge is to observe how inventory replenishment operations are processed in near real time through Confluent Cloud on Azure and reflected immediately in downstream systems like Cosmos DB or Azure AI Search. - - -## Description - -Vendors will authenticate into the system using their vendor ID and 4-digit PIN. Once authenticated, the vendor will use the AI agent to retrieve SKU-level data and issue replenishment commands. - -- Authenticate using vendor ID and 4-digit PIN. -- Retrieve: - - A list of SKUs the vendor is authorized to replenish. - - The Maximum Inventory Level (MIL) for each of those SKUs. - - The current inventory level of a specific authorized SKU. -- Replenish the inventory of an authorized SKU up to 100% of its MIL. - -All replenishment updates should be routed through Confluent Cloud and reflected in the destination data store in near real time. - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that vendor users can authenticate using ID and PIN. -- Verify that you are able to retrie a authorized SKUs and their inventory information. -- Verify a successful replenishment operation that updates inventory to the correct MIL occurs. -- Verify that inventory updates are reflected in the destination data store in near real time through Confluent Cloud. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* - -*This section is optional and may be omitted.* - -*Sample IoT advanced challenges:* - -Too comfortable? Eager to do more? Try these additional challenges! - -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md b/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md deleted file mode 100644 index 86387ad878..0000000000 --- a/xxx-AIWithConfluentOnAzure/Student/Challenge-05.md +++ /dev/null @@ -1,78 +0,0 @@ -# Challenge 05 - Simulation of Customers - Purchases and Returns - -[< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** - - -## Pre-requisites (Optional) - -You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend chat interface must be fully deployed and functional for customer interactions to work correctly. - - -## Introduction - -In this challenge, you'll simulate how customers interact with the AI agent to browse products, make purchases, and request returns. These interactions represent real-world commerce flows and depend on accurate, up-to-date inventory and pricing information. - -The goal of this challenge is to observe how customer-facing operations impact the backend in real time. All updates made through the agent—such as purchasing or returning SKUs—should flow through Confluent Cloud and be reflected in the destination datastore in near real time. - - -## Description - -Customers authenticate using a customer ID and 4-digit PIN. Once signed in, they should be able to browse available SKUs, check stock status, make purchases, and return eligible items. - -- Authenticate using customer ID and 4-digit PIN. -- Retrieve: - - A list of all SKUs available in the store, regardless of inventory. - - A list of SKUs currently in stock. - - A list of SKUs currently out of stock. - - The status of a specific SKU, including unit price, inventory level, and discount (if any). -- Add an SKU to the shopping cart (up to available inventory). -- Make a purchase for all items in the cart, generating a receipt ID. -- Retrieve transaction details for a specific receipt ID. -- Return an SKU from a previous purchase by providing a receipt ID, as long as the return is within 14 days of the purchase date. - -All purchase and return actions should be processed via Confluent Cloud and reflected in the destination datastore in near real time. - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that customer users can authenticate using ID and PIN. -- Verify you can retrie the product catalog and inventory information. -- Complete a purchase flow with a generated receipt ID. -- Show how you can return a purchased item within the allowed return window. -- Verify that purchases and returns are reflected in the destination data store in near real time through Confluent Cloud. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* - -*This section is optional and may be omitted.* - -*Sample IoT advanced challenges:* - -Too comfortable? Eager to do more? Try these additional challenges! - -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/xxx-AIWithConfluentOnAzure/Student/Resources/.gitkeep b/xxx-AIWithConfluentOnAzure/Student/Resources/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 From 516957481f63de32673374c714bb5db02ec847fe Mon Sep 17 00:00:00 2001 From: Israel Ekpo <37992436+izzymsft@users.noreply.github.com> Date: Thu, 6 Nov 2025 08:24:25 -0500 Subject: [PATCH 17/32] Add comment for upload_to_blob_storage function Added a comment to describe the upload function. --- .../Student/Resources/retail_store/azure_blob_upload.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh index 58172a6c64..92d0a0c5bc 100755 --- a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh +++ b/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh @@ -1,6 +1,6 @@ #!/bin/bash - +# Function to upload files to blob store upload_to_blob_storage() { STORAGE_ACCOUNT_NAME="${AZURE_STORAGE_ACCOUNT_NAME}" @@ -35,4 +35,4 @@ upload_to_blob_storage "departments" upload_to_blob_storage "product_pricing" upload_to_blob_storage "product_skus" -echo "All uploads completed." \ No newline at end of file +echo "All uploads completed." From 624de692bf5d8910bce8424aa689a8803fcc6443 Mon Sep 17 00:00:00 2001 From: Israel Ekpo <isekpo@microsoft.com> Date: Thu, 6 Nov 2025 10:48:58 -0500 Subject: [PATCH 18/32] Saving Changes to the Challenge Text modified: 073-AIWithConfluentOnAzure/Student/Challenge-00.md modified: 073-AIWithConfluentOnAzure/Student/Challenge-01.md modified: 073-AIWithConfluentOnAzure/Student/Challenge-02.md modified: 073-AIWithConfluentOnAzure/Student/Challenge-03.md modified: 073-AIWithConfluentOnAzure/Student/Challenge-04.md deleted: 073-AIWithConfluentOnAzure/Student/Challenge-05.md --- .../Student/Challenge-00.md | 157 +++++++++++------- .../Student/Challenge-01.md | 94 ++++++++--- .../Student/Challenge-02.md | 73 ++++---- .../Student/Challenge-03.md | 89 ++++------ .../Student/Challenge-04.md | 89 +++++----- .../Student/Challenge-05.md | 78 --------- 6 files changed, 284 insertions(+), 296 deletions(-) delete mode 100644 073-AIWithConfluentOnAzure/Student/Challenge-05.md diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-00.md b/073-AIWithConfluentOnAzure/Student/Challenge-00.md index 61aa89aa4b..08f9986c9c 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-00.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -2,99 +2,140 @@ **[Home](../README.md)** - [Next Challenge >](./Challenge-01.md) -**_This is a template for "Challenge Zero" which focuses on getting prerequisites set up for the hack. The italicized text provides hints & examples of what should or should NOT go in each section._** +## Introduction -**_We have included links to some common What The Hack pre-reqs in this template. All common prerequisite links go to the WTH-CommonPrerequisites page where there are more details on what each tool's purpose is._** +In this challenge, you will provision all required infrastructure for the hackathon—both in Azure and Confluent Cloud—using automated Terraform modules. The focus of this challenge is to set up the cloud resources needed for data ingestion, streaming, schema validation, and AI search. -**_You should remove any common pre-reqs that are not required for your hack. Then add additional pre-reqs that are required for your hack in the Description section below._** +By the end of this challenge, you should have: -**_You should remove all italicized & sample text in this template and replace with your content._** +- Confluent Cloud configured with Kafka topics, Schema Registry, and Source/Sink Connectors +- Azure resources deployed, including Cosmos DB, Azure Storage, Azure OpenAI, Redis Cache, and Azure AI Search +- MCP-powered AI agents running and able to communicate with the deployed infrastructure. -## Introduction +## Common Prerequisites -Thank you for participating in the AIWithConfluentOnAzure What The Hack. Before you can hack, you will need to set up some prerequisites. +We have compiled a list of common tools and software that you will need to complete Challenge 1 and deploy the Terraform-based infrastructure to Azure and Confluent Cloud. -## Common Prerequisites +You may not need all of them outside this challenge. However, if you work with Azure or Confluent Cloud on a regular basis, these are essential components for your development toolkit. -We have compiled a list of common tools and software that will come in handy to complete most What The Hack Azure-based hacks! +* **Azure Subscription** -You might not need all of them for the hack you are participating in. However, if you work with Azure on a regular basis, these are all things you should consider having in your toolbox. + * You must have access to an active Azure subscription with permissions to create resources. +* **Managing Cloud Resources** -<!-- If you are editing this template manually, be aware that these links are only designed to work if this Markdown file is in the /xxx-HackName/Student/ folder of your hack. --> + * **Azure Portal** + [https://portal.azure.com](https://portal.azure.com) + Used to visually validate resources deployed by Terraform. + * **Azure CLI** + [https://learn.microsoft.com/cli/azure/install-azure-cli](https://learn.microsoft.com/cli/azure/install-azure-cli) + Required to authenticate and verify your subscription and resource group. -- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) -- [Windows Subsystem for Linux](../../000-HowToHack/WTH-Common-Prerequisites.md#windows-subsystem-for-linux) -- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) - - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) - - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) - - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) - - [Azure PowerShell CmdLets](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-powershell-cmdlets) - - [Azure Cloud Shell](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cloud-shell) -- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) - - [VS Code plugin for ARM Templates](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code-plugins-for-arm-templates) -- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) + * After installation, login using: -## Description + ```bash + az login + ``` + * **Terraform CLI** + [https://developer.hashicorp.com/terraform/downloads](https://developer.hashicorp.com/terraform/downloads) + Required to deploy infrastructure modules for Azure and Confluent Cloud. -_This section should clearly state any additional prerequisite tools that need to be installed or set up in the Azure environment that the student will hack in._ + * After installation, you should be able to run the following command with the Terraform CLI: + ```bash + terraform init + ``` +* **Confluent Cloud CLI** -_While ordered lists are generally not welcome in What The Hack challenge descriptions, you can use one here in Challenge Zero IF and only IF the steps you are asking the student to perform are not core to the learning objectives of the hack._ + * Required to authenticate to Confluent Cloud and interact with Kafka topics and connectors + [https://docs.confluent.io/confluent-cli/current/install.html](https://docs.confluent.io/confluent-cli/current/install.html) -_For example, if the hack is on IoT Devices and you want the student to deploy an ARM/Bicep template that sets up the environment they will hack in without them needing to understand how ARM/Bicep templates work, you can provide step-by-step instructions on how to deploy the ARM/Bicep template._ + Use the following command to authenticate with Confluent Cloud via the CLI: + ```bash + confluent --help -_Optionally, you may provide resource files such as a sample application, code snippets, or templates as learning aids for the students. These files are stored in the hack's `Student/Resources` folder. It is the coach's responsibility to package these resources into a Resources.zip file and provide it to the students at the start of the hack. You should leave the sample text below in that refers to the Resources.zip file._ + ``` -**\*NOTE:** Do NOT provide direct links to files or folders in the What The Hack repository from the student guide. Instead, you should refer to the Resources.zip file provided by the coach.\* +Optional but helpful: -**\*NOTE:** Any direct links to the What The Hack repo will be flagged for review during the review process by the WTH V-Team, including exception cases.\* +* **Visual Studio Code** -_Sample challenge zero text for the IoT Hack Of The Century:_ + * Recommended IDE for editing Terraform configuration files + [https://code.visualstudio.com](https://code.visualstudio.com) -Now that you have the common pre-requisites installed on your workstation, there are prerequisites specifc to this hack. +* **Azure Storage Explorer** -Your coach will provide you with a Resources.zip file that contains resources you will need to complete the hack. If you plan to work locally, you should unpack it on your workstation. If you plan to use the Azure Cloud Shell, you should upload it to the Cloud Shell and unpack it there. + * Helpful for inspecting Blob Storage input files during validation + [https://azure.microsoft.com/features/storage-explorer/](https://azure.microsoft.com/features/storage-explorer/) + -Please install these additional tools: +## Description -- [Azure IoT Tools](https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-tools) extension for Visual Studio Code -- .NET SDK 6.0 or later installed on your development machine. This can be downloaded from [here](https://www.microsoft.com/net/download/all) for multiple platforms. +In this challenge, you will: -In the `/Challenge00/` folder of the Resources.zip file, you will find an ARM template, `setupIoTEnvironment.json` that sets up the initial hack environment in Azure you will work with in subsequent challenges. +1. **Clone the Hackathon Repository** (contains all Terraform modules) +2. **Update Terraform variables** with your Azure subscription ID, principal IDs, and Confluent API keys +3. **Run Terraform** to provision the infrastructure +4. **Confirm data flows through connectors** -Please deploy the template by running the following Azure CLI commands from the location of the template file: -``` -az group create --name myIoT-rg --location eastus -az group deployment create -g myIoT-rg --name HackEnvironment -f setupIoTEnvironment.json -``` +### What the Terraform automation will create -## Success Criteria +| Platform | Resource Provisioned | +| ------------------- | ---------------------------------------------------------------------------------------------------------- | +| **Azure** | Azure OpenAI, Cosmos DB, Azure AI Search, Azure Redis Cache, Azure Storage Account | +| **Confluent Cloud** | Kafka Cluster, Schema Registry, Kafka topics, Cosmos DB & Blob Source connectors, AI Search Sink connector | +| **AI Agents / MCP** | Deployment of microservices + MCP servers that expose capabilities to agents | -_Success criteria goes here. The success criteria should be a list of checks so a student knows they have completed the challenge successfully. These should be things that can be demonstrated to a coach._ +### What you will verify -_The success criteria should not be a list of instructions._ +* AI agents respond and can list the 8 departments +* Source connectors flow data from Cosmos DB and Blob Storage → Kafka topics +* Sink connector pushes data from Kafka → Azure AI Search -_Success criteria should always start with language like: "Validate XXX..." or "Verify YYY..." or "Show ZZZ..." or "Demonstrate you understand VVV..."_ +## Success Criteria -_Sample success criteria for the IoT prerequisites challenge:_ +To complete the challenge successfully, all of the following must be true: -To complete this challenge successfully, you should be able to: +* Terraform deploys successfully** and resources appear in Azure Portal and Confluent Cloud +* Source connectors are live and pushing data** from Cosmos DB and Blob Storage into Kafka topics +* Sink connector is pushing data into Azure AI Search** (net sales + net inventory count topics) +* The MCP-powered AI agent can: -- Verify that you have a bash shell with the Azure CLI available. -- Verify that the ARM template has deployed the following resources in Azure: - - Azure IoT Hub - - Virtual Network - - Jumpbox VM +* Respond when prompted +* State its name +* List all eight departments in the grocery store + +Completion checklist: + +| Objective | Verification Step | +| --------------------------------- | -------------------------------------------- | +| Azure + Confluent resources exist | Terraform output + portal checks | +| Source connectors working | Messages visible in Kafka topics | +| Sink connector working | Index documents visible in Azure AI Search | +| Agent connected | Agent responds with name + lists departments | ## Learning Resources -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ -_Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario._ +* **Install Azure CLI** + [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) + +* **Install Terraform CLI** + [Terraform CLI](https://developer.hashicorp.com/terraform/downloads) + +* **Install Confluent CLI** + [Confluent CLI](https://docs.confluent.io/confluent-cli/current/install.html) + +* **Azure Service Principal authentication** + [Azure Service Principal Setup](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal) + +* **Confluent Cloud getting started** + [Confluent Cloud on Azure](https://docs.confluent.io/cloud/current/get-started/index.html) + +* **Confluent Source & Sink Connectors** + [Kafka Connectors from Confluent](https://docs.confluent.io/cloud/current/connectors/index.html) -**\*Note:** Use descriptive text for each link instead of just URLs.\* +* **Azure AI Search documentation** + [Azure AI Search Docs](https://learn.microsoft.com/azure/search/search-what-is-azure-search) -_Sample IoT resource links:_ +* **Azure Cosmos DB documentation** + [Azure Cosmos DB Docs](https://learn.microsoft.com/azure/cosmos-db/introduction) -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-01.md b/073-AIWithConfluentOnAzure/Student/Challenge-01.md index 65ccfa2826..7f9f46f554 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-01.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -1,54 +1,94 @@ -# Challenge 01 - Configuration of Agentic Resources and Deployment of Backend +# Challenge 01 - Build the Flink Data Pipeline (Merge Streaming Data) [< Previous Challenge](./Challenge-00.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-02.md) ## Introduction -In this challenge, you'll focus on deploying the backend API that will serve as the foundation for your real-time AI agent. This API will eventually consume data streamed through Confluent Cloud on Azure and surface intelligent responses based on the latest available information. +In this challenge, you will create the streaming data pipeline that powers real-time inventory and sales updates for the online grocery store. Using Apache Flink on Confluent Cloud, you will map Kafka topics to Flink tables and merge multiple data streams (purchases, returns, pricing, departments, and replenishments) into two aggregated output tables: + +* `net_sales` +* `net_inventory_count` + +These tables will continuously update as new events stream into Kafka topics. + +--- ## Description -*Need to Update once we confirm architecture* +During this challenge, you will: +1. Connect to the Apache Flink SQL editor in Confluent Cloud. +2. Create Flink tables mapped to existing Kafka topics: -## Success Criteria + * `product_sku` + * `product_pricing` + * `product_departments` + * `purchases` + * `returns` + * `replenishments` +3. Write Flink SQL merge logic that continuously updates: -To complete this challenge successfully, you should be able to: -- Show that your Azure resources and API have been deployed -- Verify that the API is reachable and responsive. + * The `net_sales` table + * The `net_inventory_count` table -## Learning Resources +### Required Merging Logic + +* Net Sales + + * Purchases add to the net sales total for each SKU. + * Returns subtract from the net sales total for each SKU. -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +* Net Inventory Count -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* + * Purchases subtract from the inventory count. + * Replenishments add to the inventory count. + * Returns: -***Note:** Use descriptive text for each link instead of just URLs.* + * If the product belongs to the appliance department, returns add back to inventory. + * Returns from all other departments are ignored (treated as perishable or damaged). -*Sample IoT resource links:* +### Expected Outcome -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +After your SQL statements are running, every new message streaming into Kafka should update: -## Tips +* Net sales for the SKU +* Net inventory count for the SKU -*This section is optional and may be omitted.* +in real time. -*Add tips and hints here to give students food for thought. Sample IoT tips:* +--- -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +## Success Criteria + +To complete this challenge successfully, the following must be true: + +* All Kafka topics listed above are mapped to Flink tables. +* Flink SQL merge statements for `net_sales` and `net_inventory_count` are created and running. +* Sales and inventory values update continuously as new messages stream in. +* Logic behaves correctly: + + * Purchases increase net sales and decrease inventory. + * Replenishments increase inventory. + * Returns decrease net sales. + * Only appliance returns increase inventory count; all others are ignored. -## Advanced Challenges (Optional) +Completion checklist: -*If you want, you may provide additional goals to this challenge for folks who are eager.* +* [ ] Flink tables created for all source Kafka topics +* [ ] Merge query running for `net_sales` +* [ ] Merge query running for `net_inventory_count` +* [ ] Inventory and sales update in real time during event flow + +--- + +## Learning Resources -*This section is optional and may be omitted.* +* Apache Flink SQL documentation + [Apache Flink Docs](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/overview/) -*Sample IoT advanced challenges:* +* Confluent Cloud Flink quickstart + [Confluent Cloud Quickstart on Apache Flink](https://docs.confluent.io/cloud/current/flink/get-started/index.html) -Too comfortable? Eager to do more? Try these additional challenges! +* Flink SQL merge and upsert concepts + [Flink SQL Data Processing with Merge](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-02.md b/073-AIWithConfluentOnAzure/Student/Challenge-02.md index 6a5379954e..0ba4aa0852 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-02.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -1,59 +1,66 @@ -# Challenge 02 - Configuration of Chat Interface and Frontend +# Challenge 02 - Supplier Experience [< Previous Challenge](./Challenge-01.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-03.md) ## Pre-requisites -You must complete **Challenge 01** before starting this challenge. The backend API must be successfully deployed and reachable, as the frontend will depend on it for communication and functionality. +You must complete **Challenge 01** before starting this challenge. The data pipeline with Flink SQL is necessary for this experience to function properly. ## Introduction -In this challenge, you'll configure and deploy the frontend user interface that interacts with your backend API. This frontend UI will allow users to send and receive messages to the AI agent powered by real-time streaming data from Confluent Cloud. **Need to update as I am just filling in generic verbiage** - +In this challenge, you will assume the role of a supplier interacting with the AI agent experience. The purpose of this challenge is to demonstrate how the data pipeline created in previous challenges provides real-time, accurate inventory information to the agent through MCP services backed by Apache Flink. As inventory levels change, Flink continuously merges data streams and updates the net inventory count table, ensuring that the supplier receives the most up-to-date information at all times. ## Description -**Need to Update as we get details of infrastructure. - -## Success Criteria +During this challenge, you will: -To complete this challenge successfully, you should be able to: -- Show that your frontend and related Azure resources have been deployed. -- Verify that the frontend can communicate with the backend API and receive a valid response. - -## Learning Resources +1. Log into the supplier agent experience. +2. Use the agent to query inventory levels across departments and product SKUs. +3. Replenish inventory by instructing the agent to update stock levels for specific SKUs or entire departments. +4. Verify in Azure AI Search that inventory data is being updated. +5. Confirm that the AI agent responds with accurate, real-time inventory values by querying the MCP service. -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ +Tasks to complete: -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +* View inventory levels for product SKUs within a specific department. +* View inventory level of a specific product SKU. +* Replenish inventory for a specific SKU. +* Replenish all SKUs within a department. +* Verify that inventory changes are reflected in Azure AI Search. +* Verify that the agent reflects accurate inventory levels based on the streaming data pipeline. -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +## Success Criteria -## Tips +This challenge is complete when the following conditions are met: -*This section is optional and may be omitted.* +* The supplier agent can display real-time inventory levels for any SKU. +* The supplier agent can display real-time inventory levels per department. +* Replenishment actions result in updated inventory values in the net inventory count table. +* Azure AI Search reflects the updated inventory counts for specific SKUs. +* The agent retrieves updated values from MCP services and responds accurately after inventory changes. -*Add tips and hints here to give students food for thought. Sample IoT tips:* +Completion checklist: -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +* [ ] Agent successfully retrieves inventory by SKU. +* [ ] Agent successfully retrieves inventory by department. +* [ ] Replenishment action updates inventory for an individual SKU. +* [ ] Replenishment action updates inventory for all SKUs within a department. +* [ ] Updated inventory values are reflected in Azure AI Search. +* [ ] Updated inventory values are returned correctly by the agent. -## Advanced Challenges (Optional) +--- -*If you want, you may provide additional goals to this challenge for folks who are eager.* +## Learning Resources -*This section is optional and may be omitted.* +* Working with Apache Flink SQL in Confluent Cloud + [https://docs.confluent.io/cloud/current/flink/get-started/index.html](https://docs.confluent.io/cloud/current/flink/get-started/index.html) -*Sample IoT advanced challenges:* +* Using Azure AI Search as a real-time index + [https://learn.microsoft.com/azure/search/search-what-is-azure-search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) -Too comfortable? Eager to do more? Try these additional challenges! +* Schema Registry and data contracts + [https://docs.confluent.io/platform/current/schema-registry/index.html](https://docs.confluent.io/platform/current/schema-registry/index.html) -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +* Kafka Connect Source and Sink Connectors + [https://docs.confluent.io/cloud/current/connectors/index.html](https://docs.confluent.io/cloud/current/connectors/index.html) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-03.md b/073-AIWithConfluentOnAzure/Student/Challenge-03.md index 539e22e5a1..b5efc3c9ab 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-03.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -1,80 +1,63 @@ -# Challenge 03 - Simulation of Employee Persona +# Challenge 03 - Customer Experience [< Previous Challenge](./Challenge-02.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-04.md) ## Pre-requisites -You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend interface must be fully deployed and functional, as this challenge builds on top of the running application infrastructure. +You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The data pipeline with Flink SQL is necessary for this experience to function properly. ## Introduction -In this challenge, you'll simulate the experience of an employee interacting with the AI agent to perform various business-critical operations. This persona has access to operational data such as purchases, returns, and inventory, and can also perform updates to the product catalog in near real time. - -The goal of this challenge is to observe how changes initiated through the agent are processed and reflected across systems in near real time using Confluent Cloud on Azure. These updates—whether querying data or modifying records—flow through Kafka topics, are processed via stream processors like Flink or ksqlDB, and are reflected in the destination datastore with minimal delay. - +In this challenge, you will assume the role of a customer interacting with the customer agent experience. The purpose of this challenge is to demonstrate real-time event processing as purchase and return actions affect inventory levels. When a customer makes a purchase or return, Apache Flink processes the streaming events and updates the net sales and net inventory count tables, which are then indexed into Azure AI Search and made available to the agent. ## Description -In this challenge, you will authenticate as an employee and issue commands to the AI agent to retrieve and update retail operations data. These interactions are routed through the backend API, processed via Confluent Cloud's real-time data infrastructure, and ultimately reflected in the destination datastore. +During this challenge, you will: -- Authenticate using an employee ID and 4-digit PIN. -- Retrieve summaries for a specific date: - - Total purchases - - Total replenishments - - Total returns - - Net sales (purchases - returns) -- Query current inventory level of a specific SKU. -- Modify inventory-related data: - - Change the maximum inventory level of a specific SKU. - - Update the unit price of a specific SKU. - - Add a new SKU to the product catalog. - - Modify the list of SKUs a vendor is authorized to replenish. +1. Log into the customer agent experience. +2. View inventory levels before purchasing items. +3. Perform a purchase action for one or more product SKUs. +4. Perform a return action for selected product SKUs. +5. Validate that inventory and sales data update in real time. -All modifications should propagate through Confluent Cloud and be reflected in the destination data store (e.g., Cosmos DB or Azure AI Search) in near real time. +Tasks to complete: +* View inventory levels for a specific product SKU before purchasing. +* Purchase product SKUs from different departments and record the quantities purchased. +* Return product SKUs from each department and record the quantities returned. +* After each purchase and return event, view the updated inventory to confirm changes. +* Ensure that inventory updates occur within a three-second window. ## Success Criteria -To complete this challenge successfully, you should be able to: -- Show that employee users can authenticate using ID and PIN. -- Show at least three successful read operations. -- Show at least two successful write operations. -- Verify that data changes propagate through Confluent Cloud and are reflected in the destination data store in near real time. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +This challenge is complete when the following conditions are met: -***Note:** Use descriptive text for each link instead of just URLs.* +* The customer agent displays the inventory level of a SKU before a purchase. +* After a purchase, inventory is reduced and net sales are updated. +* After a return, inventory and net sales are updated following the business rules defined in the Flink merge logic. +* All inventory updates are visible within three seconds of the action being completed. +* The agent retrieves accurate, real-time values via MCP services backed by Azure AI Search. -*Sample IoT resource links:* +Completion checklist: -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) +* [ ] Customer can view inventory for a SKU before purchasing. +* [ ] Customer executes a purchase and observes updated values. +* [ ] Customer executes a return and observes updated values. +* [ ] Updated inventory and sales values are reflected within the required three-second threshold. +* [ ] Inventory and sales values shown by the agent match values in Azure AI Search and Flink. -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* +## Learning Resources -*This section is optional and may be omitted.* +* Confluent Cloud Flink quickstart + [https://docs.confluent.io/cloud/current/flink/get-started/index.html](https://docs.confluent.io/cloud/current/flink/get-started/index.html) -*Sample IoT advanced challenges:* +* Event processing and upsert patterns in Apache Flink + [https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) -Too comfortable? Eager to do more? Try these additional challenges! +* Azure AI Search indexing concepts + [https://learn.microsoft.com/azure/search/search-what-is-azure-search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +* Kafka event streaming fundamentals + [https://kafka.apache.org/documentation/](https://kafka.apache.org/documentation/) \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-04.md b/073-AIWithConfluentOnAzure/Student/Challenge-04.md index f225b41ef7..68eea78a47 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-04.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -1,73 +1,68 @@ -# Challenge 04 - Simulation of Suppliers - Replenishments +# Challenge 04 - Employee Experience -[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** - [Next Challenge >](./Challenge-05.md) +[< Previous Challenge](./Challenge-03.md) - **[Home](../README.md)** ## Pre-requisites -You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend, frontend, and employee data operations must be functional to ensure supplier-related workflows integrate with the rest of the system. +You must complete **Challenge 02** and **Challenge 03** before starting this challenge. The data pipeline from the replenishments, returns and purchases is necessary for this experience to be complete and successful. ## Introduction -In this challenge, you’ll take on the role of a vendor or supplier interacting with the AI agent to monitor and replenish inventory levels. These interactions are authorized and scoped to SKUs each vendor is allowed to manage. - -The goal of this challenge is to observe how inventory replenishment operations are processed in near real time through Confluent Cloud on Azure and reflected immediately in downstream systems like Cosmos DB or Azure AI Search. +In this challenge, you will assume the role of an employee interacting with the employee agent experience. The objective is to demonstrate the employee's ability to access comprehensive operational insights, including inventory, cumulative metrics, and net sales for each product SKU. The employee agent uses the same MCP service and data pipeline powered by Apache Flink, with data originating from real-time events such as purchases, returns, and replenishments. +This challenge requires interaction across multiple personas. You will switch between customer, supplier, and employee tabs or windows to simulate real-world concurrent activity. Each action triggers updates to the net inventory count and net sales tables, and the employee agent should always return accurate, real-time data. ## Description -Vendors will authenticate into the system using their vendor ID and 4-digit PIN. Once authenticated, the vendor will use the AI agent to retrieve SKU-level data and issue replenishment commands. - -- Authenticate using vendor ID and 4-digit PIN. -- Retrieve: - - A list of SKUs the vendor is authorized to replenish. - - The Maximum Inventory Level (MIL) for each of those SKUs. - - The current inventory level of a specific authorized SKU. -- Replenish the inventory of an authorized SKU up to 100% of its MIL. - -All replenishment updates should be routed through Confluent Cloud and reflected in the destination data store in near real time. - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that vendor users can authenticate using ID and PIN. -- Verify that you are able to retrie a authorized SKUs and their inventory information. -- Verify a successful replenishment operation that updates inventory to the correct MIL occurs. -- Verify that inventory updates are reflected in the destination data store in near real time through Confluent Cloud. +During this challenge, you will: -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* +1. Log into the employee agent experience. +2. Query real-time inventory and cumulative transaction metrics. +3. Use other personas (customer and supplier) to trigger purchase, return, and replenishment events. +4. Confirm that the employee agent responds with accurate values based on the updated data pipeline. -***Note:** Use descriptive text for each link instead of just URLs.* +Tasks to complete: -*Sample IoT resource links:* +* View inventory levels for any product SKU. +* View inventory levels for all product SKUs within a department. +* Retrieve cumulative purchase units for any SKU after a purchase event. +* Retrieve cumulative return units for any SKU after a return event. +* Retrieve cumulative replenishment units for any SKU after a supplier replenishment event. +* Retrieve the net inventory count for any SKU after any event. +* Retrieve the net sales numbers for any SKU after events are finalized. -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips +## Success Criteria -*This section is optional and may be omitted.* +This challenge is complete when the following conditions are met: -*Add tips and hints here to give students food for thought. Sample IoT tips:* +* The employee agent can display inventory levels for individual SKUs. +* The employee agent can display inventory levels for all SKUs in a department. +* Cumulative purchase, return, and replenishment values for any SKU are retrieved accurately. +* The agent provides accurate net inventory counts and net sales values after transactions. +* Inventory and sales values shown by the agent match what is observed in Azure AI Search and Flink output. -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. +Completion checklist: -## Advanced Challenges (Optional) +* [ ] Employee agent retrieves current inventory for a SKU. +* [ ] Employee agent retrieves inventory for a department. +* [ ] Cumulative purchase units update after customer purchase events. +* [ ] Cumulative return units update after customer return events. +* [ ] Cumulative replenishment units update after supplier replenishment events. +* [ ] Net inventory count is accurate after each event type. +* [ ] Net sales values update correctly after each event type. -*If you want, you may provide additional goals to this challenge for folks who are eager.* +## Learning Resources -*This section is optional and may be omitted.* +* Confluent Cloud Flink quickstart + [https://docs.confluent.io/cloud/current/flink/get-started/index.html](https://docs.confluent.io/cloud/current/flink/get-started/index.html) -*Sample IoT advanced challenges:* +* Flink SQL upsert and aggregate patterns + [https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) -Too comfortable? Eager to do more? Try these additional challenges! +* Azure AI Search indexing concepts + [https://learn.microsoft.com/azure/search/search-what-is-azure-search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. +* Kafka event streaming fundamentals + [https://kafka.apache.org/documentation/](https://kafka.apache.org/documentation/) \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-05.md b/073-AIWithConfluentOnAzure/Student/Challenge-05.md deleted file mode 100644 index 86387ad878..0000000000 --- a/073-AIWithConfluentOnAzure/Student/Challenge-05.md +++ /dev/null @@ -1,78 +0,0 @@ -# Challenge 05 - Simulation of Customers - Purchases and Returns - -[< Previous Challenge](./Challenge-04.md) - **[Home](../README.md)** - - -## Pre-requisites (Optional) - -You must complete **Challenge 01** and **Challenge 02** before starting this challenge. The backend API and frontend chat interface must be fully deployed and functional for customer interactions to work correctly. - - -## Introduction - -In this challenge, you'll simulate how customers interact with the AI agent to browse products, make purchases, and request returns. These interactions represent real-world commerce flows and depend on accurate, up-to-date inventory and pricing information. - -The goal of this challenge is to observe how customer-facing operations impact the backend in real time. All updates made through the agent—such as purchasing or returning SKUs—should flow through Confluent Cloud and be reflected in the destination datastore in near real time. - - -## Description - -Customers authenticate using a customer ID and 4-digit PIN. Once signed in, they should be able to browse available SKUs, check stock status, make purchases, and return eligible items. - -- Authenticate using customer ID and 4-digit PIN. -- Retrieve: - - A list of all SKUs available in the store, regardless of inventory. - - A list of SKUs currently in stock. - - A list of SKUs currently out of stock. - - The status of a specific SKU, including unit price, inventory level, and discount (if any). -- Add an SKU to the shopping cart (up to available inventory). -- Make a purchase for all items in the cart, generating a receipt ID. -- Retrieve transaction details for a specific receipt ID. -- Return an SKU from a previous purchase by providing a receipt ID, as long as the return is within 14 days of the purchase date. - -All purchase and return actions should be processed via Confluent Cloud and reflected in the destination datastore in near real time. - -## Success Criteria - -To complete this challenge successfully, you should be able to: -- Show that customer users can authenticate using ID and PIN. -- Verify you can retrie the product catalog and inventory information. -- Complete a purchase flow with a generated receipt ID. -- Show how you can return a purchased item within the allowed return window. -- Verify that purchases and returns are reflected in the destination data store in near real time through Confluent Cloud. - -## Learning Resources - -_List of relevant links and online articles that should give the attendees the knowledge needed to complete the challenge._ - -*Think of this list as giving the students a head start on some easy Internet searches. However, try not to include documentation links that are the literal step-by-step answer of the challenge's scenario.* - -***Note:** Use descriptive text for each link instead of just URLs.* - -*Sample IoT resource links:* - -- [What is a Thingamajig?](https://www.bing.com/search?q=what+is+a+thingamajig) -- [10 Tips for Never Forgetting Your Thingamajic](https://www.youtube.com/watch?v=dQw4w9WgXcQ) -- [IoT & Thingamajigs: Together Forever](https://www.youtube.com/watch?v=yPYZpwSpKmA) - -## Tips - -*This section is optional and may be omitted.* - -*Add tips and hints here to give students food for thought. Sample IoT tips:* - -- IoTDevices can fail from a broken heart if they are not together with their thingamajig. Your device will display a broken heart emoji on its screen if this happens. -- An IoTDevice can have one or more thingamajigs attached which allow them to connect to multiple networks. - -## Advanced Challenges (Optional) - -*If you want, you may provide additional goals to this challenge for folks who are eager.* - -*This section is optional and may be omitted.* - -*Sample IoT advanced challenges:* - -Too comfortable? Eager to do more? Try these additional challenges! - -- Observe what happens if your IoTDevice is separated from its thingamajig. -- Configure your IoTDevice to connect to BOTH the mothership and IoTQueenBee at the same time. From b7c6a7083134a72e337eefae3c8a8ac567e33f16 Mon Sep 17 00:00:00 2001 From: Israel Ekpo <isekpo@microsoft.com> Date: Thu, 6 Nov 2025 11:18:32 -0500 Subject: [PATCH 19/32] saving changes for Kafka connect --- 073-AIWithConfluentOnAzure/Student/Challenge-00.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-00.md b/073-AIWithConfluentOnAzure/Student/Challenge-00.md index 08f9986c9c..3ecdc6af3b 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-00.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -65,7 +65,7 @@ Optional but helpful: * Helpful for inspecting Blob Storage input files during validation [https://azure.microsoft.com/features/storage-explorer/](https://azure.microsoft.com/features/storage-explorer/) - + ## Description @@ -130,6 +130,9 @@ Completion checklist: * **Confluent Cloud getting started** [Confluent Cloud on Azure](https://docs.confluent.io/cloud/current/get-started/index.html) +* **Confluent Connector Hub** + [Azure Connectors for Confluent](https://www.confluent.io/hub/plugins?query=azure) + * **Confluent Source & Sink Connectors** [Kafka Connectors from Confluent](https://docs.confluent.io/cloud/current/connectors/index.html) From ac9328127438ff9300f99002a3a44ce2ad0b5dd4 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Wed, 12 Nov 2025 16:42:15 -0800 Subject: [PATCH 20/32] Initial updates to follow guidelines and update names of challenges/readme --- .github/chatmodes/WTHAuthor.chatmode.md | 316 ++++++++++++++++++ 073-AIWithConfluentOnAzure/Coach/README.md | 20 +- .../Coach/Solution-00.md | 2 +- .../Coach/Solution-01.md | 2 +- .../Coach/Solution-02.md | 2 +- .../Coach/Solution-03.md | 2 +- .../Coach/Solution-04.md | 4 +- .../Coach/Solution-05.md | 20 -- 073-AIWithConfluentOnAzure/README.md | 20 +- .../Student/Challenge-00.md | 36 +- .../Student/Challenge-01.md | 60 +--- .../Student/Challenge-02.md | 60 ++-- .../Student/Challenge-03.md | 55 ++- .../Student/Challenge-04.md | 59 ++-- 14 files changed, 428 insertions(+), 230 deletions(-) create mode 100644 .github/chatmodes/WTHAuthor.chatmode.md delete mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-05.md diff --git a/.github/chatmodes/WTHAuthor.chatmode.md b/.github/chatmodes/WTHAuthor.chatmode.md new file mode 100644 index 0000000000..664255cb7b --- /dev/null +++ b/.github/chatmodes/WTHAuthor.chatmode.md @@ -0,0 +1,316 @@ +--- +description: 'What The Hack content authoring assistant - helps create challenge-based hackathon content following WTH guidelines' +--- + +# What The Hack Content Authoring Assistant + +You are a specialized assistant for authoring What The Hack (WTH) content. What The Hack is a challenge-based hackathon format where participants learn through hands-on problem-solving rather than step-by-step instructions. + +**IMPORTANT INSTRUCTIONS:** +1. When reviewing or fixing WTH content, IMPLEMENT the changes directly using file editing tools rather than just suggesting them. Only explain what you're doing without asking for permission first. +2. ALWAYS review ALL WTH guidelines and requirements listed below BEFORE completing any task. Ensure every requirement is met - do not skip or forget any guideline. +3. You are EMPOWERED to restructure content to match WTH templates: + - Remove sections that don't belong in the template + - Rename sections to match template naming conventions + - Reorder sections to match the required template structure + - Add missing required sections +4. After making changes, verify that ALL WTH compliance rules have been followed, especially: + - No ordered/numbered lists in challenge descriptions (EXCEPT Challenge 00 - Prerequisites) + - No links from student content to coach solutions or WTH repo + - Success criteria use action verbs (Verify, Validate, Demonstrate, Show) + - All links have descriptive text (no bare URLs) + - Section names and structure match the official templates + - Correct spelling and capitalization of all Azure services and technology names (e.g., "Azure Kubernetes Service" not "azure kubernetes service", "Cosmos DB" not "CosmosDB") + +## Core Principles + +- **Challenge-Based Learning**: WTH is about making attendees learn by solving problems, NOT blindly following step-by-step instructions +- **Share After Event**: Content can be shared with attendees ONLY after the event is over +- **Coach Separation**: Student content must never link to Coach solutions or the WTH GitHub repo + +## Required Hack Structure + +Every What The Hack consists of: + +### 1. Hack Description (README.md in hack root) +**Must include:** +- **Hack Title**: Short but fun name, more than just technology names +- **Introduction**: Sell the hack - what technologies, why they matter, real-world scenarios (1-2 paragraphs) +- **Learning Objectives**: Short list of key learnings/outcomes +- **Challenges**: List of challenges with one-sentence descriptions, linked to individual challenge pages +- **Prerequisites(Optional)**: + - Assumed knowledge (e.g., "basic understanding of containers") + - Required tools/software + - Link to WTH Common Prerequisites if applicable +- **Repository Contents** (Optional): Catalog of provided files +- **Contributors**: Names and optional contact info of authors + +### 2. Challenge Files (Student/ChallengeXX.md) + +**Structure:** +- Navigation links (previous/home/next) using relative paths +- **Pre-requisites** (Optional): If specific previous challenges required +- **Introduction**: Overview of technologies/tasks, technical context, new lessons +- **Description**: Clear goals and high-level instructions (2-3 paragraphs max) + - Use bullet lists, NOT ordered lists (no step-by-step!) + - **EXCEPTION**: Challenge 00 (Prerequisites) MAY use ordered/numbered lists and step-by-step instructions since it's focused on setup, not core learning objectives + - May use sub-headers to organize sections + - Reference resources from Resources.zip provided by coach (OR Codespaces if the hack includes a devcontainer) + - NO direct links to WTH repo (exception: raw links to PDFs/Office docs) +- **Success Criteria**: Verifiable checks (start with "Validate...", "Verify...", "Show...", "Demonstrate...") +- **Learning Resources**: Relevant links with descriptive text (not just URLs) +- **Tips** (Optional): Hints and food for thought +- **Advanced Challenges** (Optional): Extra goals for eager participants + +**Key Rules:** +- NO step-by-step instructions (except Challenge 00) +- Multiple solution paths are OK +- Provide verifiable success criteria +- Include relevant learning resources +- Hint at time-consuming low-value items + +### 3. Challenge Design Principles + +**Include Challenge 0**: Helps attendees install all prerequisites +- Challenge 00 is the ONLY challenge where step-by-step instructions and ordered lists are permitted +- May provide detailed setup instructions for tools, environments, and dependencies + +**Cumulative Challenges:** +- Start small and simple ("Hello World") +- Build progressively more complex but allow for modularity for students to cherry pick content +- Establish confidence → Build competence +- Each challenge has educational value (even if only 3 of 7 completed) + + +### 4. Student Resources (Student/Resources/) + +- Provide code, templates, samples, or artifacts for challenges +- ideally a codespace to allow for most pre-req to be installed + +### 5. Coach's Guide (Coach/README.md) + +**The "owner's manual" for future coaches, including:** +- High-level solution steps to each challenge +- Known blockers and recommended hints +- Key concepts to explain before each challenge +- Reference links/articles/documentation for when students stuck +- Estimated time per challenge (NOT for students) + +### 6. Coach Solutions (Coach/Solutions/) + +- Example solutions (one way to solve challenges) +- Full working applications, configs, templates +- Prerequisites for Azure environment if needed +- Scripts/templates to share if teams really stuck +- NOT intended for attendees before/during event (but publicly available) + +## Directory Structure + +``` +XXX-YourHackName/ +├── README.md (Hack Description) +├── Coach/ +│ ├── README.md (Coach's Guide) +│ ├── Solution-01.md +│ ├── Solution-02.md +│ ├── ... +│ ├── Lectures.pptx (Optional) +│ └── Solutions/ +│ ├── (example code) +│ ├── (templates) +│ └── (configs) +└── Student/ + ├── Challenge-00.md + ├── Challenge-01.md + ├── Challenge-02.md + ├── ... + └── Resources/ + ├── (sample code) + ├── (templates) + └── (artifacts) +``` + +## Content Guidelines + +### What to DO: +- ✅ Use bullet lists for goals and specifications +- ✅ Use relative links for navigation (./ChallengeXX.md) +- ✅ Use descriptive link text (not bare URLs) +- ✅ Refer to Resources.zip in student challenges +- ✅ Keep challenge descriptions concise (shorter than the authoring guide!) +- ✅ Provide verifiable success criteria +- ✅ Include relevant learning resources +- ✅ Allow multiple solution paths +- ✅ Hint at time-consuming low-value items + +### What NOT to DO: +- ❌ NO step-by-step instructions in student challenges +- ❌ NO ordered/numbered lists in challenge descriptions (indicates step-by-step) +- ❌ NO links from student guide to WTH repo or Coach solutions +- ❌ NO absolute links to WTH repo (use relative links) +- ❌ NO bare URLs (use descriptive link text) +- ❌ NO sharing success criteria time estimates with students +- ❌ NO making challenges too verbose + +## Templates Available + +All templates are in `000-HowToHack/`: +- `WTH-HackDescription-Template.md` → Hack README.md +- `WTH-Challenge-Template.md` → Student/ChallengeXX.md +- `WTH-CoachGuide-Template.md` → Coach/README.md +- `WTH-Challenge-Solution-Template.md` → Coach/Solution-XX.md +- `WTH-ChallengeZero-Template.md` → Student/Challenge-00.md + +## Your Role as Authoring Assistant + +When helping authors: + +1. **Structure Guidance**: Help create proper directory structure and file organization +2. **Content Review**: Check that content follows WTH guidelines +3. **Template Usage**: Guide authors to use appropriate templates +4. **Challenge Design**: Ensure challenges are educational, progressive, and verifiable +5. **Link Validation**: Verify no student-to-coach or repo links +6. **Tone Check**: Ensure concise, challenge-based (not step-by-step) language +7. **Success Criteria**: Help write verifiable success criteria +8. **Resource Organization**: Guide proper placement of student vs coach resources + +Always remind authors that: +- Challenges should make attendees LEARN by solving problems +- Content will be publicly available (attendees can find it if determined) +- Coach's Guide can be written post-event based on first run learnings +- Quality content takes time but the format makes it easier to maintain + +## Quick Reference Checklist + +When reviewing/creating WTH content: + +**Hack Description (README.md):** +- [ ] Has engaging title and introduction +- [ ] Lists clear learning objectives +- [ ] Lists all challenges with descriptions +- [ ] Specifies prerequisites (knowledge + tools) +- [ ] Credits all contributors + +**Student Challenges:** +- [ ] Has navigation links (relative paths) +- [ ] Introduction provides context +- [ ] Description is concise (not step-by-step) +- [ ] Uses bullet lists (not ordered lists) +- [ ] Has verifiable success criteria +- [ ] Includes learning resources with descriptive links +- [ ] NO links to WTH repo or Coach solutions +- [ ] Correct spelling and capitalization of Azure/tech service names + +**Coach's Guide:** +- [ ] Has navigation links (relative paths) +- [ ] High-level solution steps +- [ ] Known blockers and hints +- [ ] Time estimates per challenge +- [ ] Key concepts to explain +- [ ] Reference materials + +**Coach Solutions:** +- [ ] Example working solutions +- [ ] Templates/scripts to share if stuck +- [ ] Pre-req setup instructions + +**Structure:** +- [ ] Proper directory layout (Coach/, Student/, Student/Resources/) +- [ ] Challenge numbering starts at 00 +- [ ] All navigation links work +- [ ] Resources properly packaged + +## Azure & Technology Service Name Standards + +When reviewing content, verify correct spelling and capitalization of service names: + +**Common Azure Services:** +- Azure Kubernetes Service (AKS) - not "Azure Kubernetes Services" +- Azure Container Instances (ACI) +- Azure Cosmos DB - not "CosmosDB" or "Cosmos Db" +- Azure OpenAI - not "Azure Open AI" +- Azure AI Search - not "Azure Search" or "Azure Cognitive Search" (legacy name) +- Azure Functions - not "Azure Function" +- Azure App Service - not "App Services" +- Azure Storage Account +- Azure Virtual Machines (VMs) +- Azure SQL Database - not "Azure SQL DB" +- Azure Key Vault - not "Key vault" or "KeyVault" +- Azure Monitor +- Azure DevOps +- Azure Active Directory (Azure AD) or Microsoft Entra ID (newer name) +- Azure Container Registry (ACR) + +**Other Technologies:** +- Terraform - not "terraform" +- Kubernetes - not "kubernetes" or "K8s" in formal documentation +- Docker - not "docker" +- GitHub - not "Github" +- Visual Studio Code (VS Code) + +## Common Violations to Flag + +### ❌ BAD: Ordered Lists (Step-by-Step) +```markdown +1. First, create a resource group +2. Next, deploy the ARM template +3. Finally, verify the deployment +``` + +### ✅ GOOD: Bullet Lists (Challenge-Based) +```markdown +- Create a resource group for your resources +- Deploy infrastructure using Infrastructure as Code +- Verify all resources are running correctly +``` + +--- + +### ❌ BAD: Links to Coach/Repo +```markdown +[Solution](../../Coach/Solution-01.md) +[Code](https://github.com/Microsoft/WhatTheHack/...) +``` + +### ✅ GOOD: Reference Resources.zip +```markdown +Refer to the starter code in the Resources.zip file provided by your coach. +``` + +--- + +### ❌ BAD: Vague Success Criteria +```markdown +- Understand how containers work +- Learn about Kubernetes +``` + +### ✅ GOOD: Verifiable Success Criteria +```markdown +- Verify your container is running using `docker ps` +- Demonstrate that your pod is in Running state +- Show that your application responds to HTTP requests +``` + +--- + +### ❌ BAD: Bare URLs +```markdown +https://docs.microsoft.com/azure/... +``` + +### ✅ GOOD: Descriptive Links +```markdown +[Azure Container Instances Documentation](https://docs.microsoft.com/azure/...) +``` + +## Response Style + +When helping with WTH content: +- Point out violations of WTH guidelines clearly +- Suggest rewording step-by-step text as challenge-based goals +- Flag any student→coach or student→repo links immediately +- Recommend using templates for new content +- Validate structure matches required format +- Check that success criteria are verifiable +- Ensure learning resources are relevant and descriptive \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Coach/README.md b/073-AIWithConfluentOnAzure/Coach/README.md index aa8938734d..9b2a0d597e 100644 --- a/073-AIWithConfluentOnAzure/Coach/README.md +++ b/073-AIWithConfluentOnAzure/Coach/README.md @@ -11,17 +11,15 @@ This hack includes an optional [lecture presentation](Lectures.pptx) that featur ## Coach's Guides - Challenge 00: **[Prerequisites - Ready, Set, GO!](./Solution-00.md)** - - Prepare your workstation to work with Azure. -- Challenge 01: **[Title of Challenge](./Solution-01.md)** - - Description of challenge -- Challenge 02: **[Title of Challenge](./Solution-02.md)** - - Description of challenge -- Challenge 03: **[Title of Challenge](./Solution-03.md)** - - Description of challenge -- Challenge 04: **[Title of Challenge](./Solution-04.md)** - - Description of challenge -- Challenge 05: **[Title of Challenge](./Solution-05.md)** - - Description of challenge + - Prepare Azure and Confluent Cloud environments with required infrastructure +- Challenge 01: **[Build the Flink Data Pipeline](./Solution-01.md)** + - Create streaming data pipeline that merges multiple data streams using Apache Flink +- Challenge 02: **[Supplier Experience](./Solution-02.md)** + - Interact with the AI agent as a supplier to query and replenish inventory +- Challenge 03: **[Customer Experience](./Solution-03.md)** + - Simulate customer purchases and returns with real-time inventory updates +- Challenge 04: **[Employee Experience](./Solution-04.md)** + - Access comprehensive operational insights across all transactions ## Coach Prerequisites diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-00.md b/073-AIWithConfluentOnAzure/Coach/Solution-00.md index 8ca1a44d71..6ae2d64d2b 100644 --- a/073-AIWithConfluentOnAzure/Coach/Solution-00.md +++ b/073-AIWithConfluentOnAzure/Coach/Solution-00.md @@ -1,4 +1,4 @@ -# Challenge 00 - <Title of Challenge> - Coach's Guide +# Challenge 00 - Prerequisites - Ready, Set, GO! - Coach's Guide **[Home](./README.md)** - [Next Solution >](./Solution-01.md) diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-01.md b/073-AIWithConfluentOnAzure/Coach/Solution-01.md index 01d1e30c27..21709a8252 100644 --- a/073-AIWithConfluentOnAzure/Coach/Solution-01.md +++ b/073-AIWithConfluentOnAzure/Coach/Solution-01.md @@ -1,4 +1,4 @@ -# Challenge 01 - <Title of Challenge> - Coach's Guide +# Challenge 01 - Build the Flink Data Pipeline - Coach's Guide [< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-02.md b/073-AIWithConfluentOnAzure/Coach/Solution-02.md index 1ef8ca5035..be03319418 100644 --- a/073-AIWithConfluentOnAzure/Coach/Solution-02.md +++ b/073-AIWithConfluentOnAzure/Coach/Solution-02.md @@ -1,4 +1,4 @@ -# Challenge 02 - <Title of Challenge> - Coach's Guide +# Challenge 02 - Supplier Experience - Coach's Guide [< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-03.md b/073-AIWithConfluentOnAzure/Coach/Solution-03.md index 9591196509..0f5569b237 100644 --- a/073-AIWithConfluentOnAzure/Coach/Solution-03.md +++ b/073-AIWithConfluentOnAzure/Coach/Solution-03.md @@ -1,4 +1,4 @@ -# Challenge 03 - <Title of Challenge> - Coach's Guide +# Challenge 03 - Customer Experience - Coach's Guide [< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-04.md b/073-AIWithConfluentOnAzure/Coach/Solution-04.md index 90a770fdb3..eb403c74fe 100644 --- a/073-AIWithConfluentOnAzure/Coach/Solution-04.md +++ b/073-AIWithConfluentOnAzure/Coach/Solution-04.md @@ -1,6 +1,6 @@ -# Challenge 04 - <Title of Challenge> - Coach's Guide +# Challenge 04 - Employee Experience - Coach's Guide -[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - [Next Solution >](./Solution-05.md) +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** ## Notes & Guidance diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-05.md b/073-AIWithConfluentOnAzure/Coach/Solution-05.md deleted file mode 100644 index c320bf9745..0000000000 --- a/073-AIWithConfluentOnAzure/Coach/Solution-05.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 05 - <Title of Challenge> - Coach's Guide - -[< Previous Solution](./Solution-04.md) - **[Home](./README.md)** - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/073-AIWithConfluentOnAzure/README.md b/073-AIWithConfluentOnAzure/README.md index f693803823..6c74e32238 100644 --- a/073-AIWithConfluentOnAzure/README.md +++ b/073-AIWithConfluentOnAzure/README.md @@ -20,17 +20,15 @@ By completing this hack, you will: ## Challenges - Challenge 00: **[Prerequisites - Ready, Set, GO!](Student/Challenge-00.md)** - - Prepare your workstation to work with Azure. -- Challenge 01: **[Configuration of Agentic Resources and Deployment of Backend](Student/Challenge-01.md)** - - Description of challenge -- Challenge 02: **[Configuration of Chat Interface and Frontend](Student/Challenge-02.md)** - - Description of challenge -- Challenge 03: **[Simulation of Employee - Reports, Status etc](Student/Challenge-03.md)** - - Description of challenge -- Challenge 04: **[Simulation of Suppliers - Replenishments](Student/Challenge-04.md)** - - Description of challenge -- Challenge 05: **[Simulation of Customers - Purchases and Returns](Student/Challenge-05.md)** - - Description of challenge + - Prepare your Azure and Confluent Cloud environments with required infrastructure +- Challenge 01: **[Build the Flink Data Pipeline](Student/Challenge-01.md)** + - Create streaming data pipeline that merges multiple data streams using Apache Flink +- Challenge 02: **[Supplier Experience](Student/Challenge-02.md)** + - Interact with the AI agent as a supplier to query and replenish inventory +- Challenge 03: **[Customer Experience](Student/Challenge-03.md)** + - Simulate customer purchases and returns with real-time inventory updates +- Challenge 04: **[Employee Experience](Student/Challenge-04.md)** + - Access comprehensive operational insights across all transactions ## Prerequisites diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-00.md b/073-AIWithConfluentOnAzure/Student/Challenge-00.md index 3ecdc6af3b..c0f25516cd 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-00.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -69,9 +69,11 @@ Optional but helpful: ## Description +Your coach will provide you with a Resources.zip file (or access to a Codespaces environment) that contains the Terraform modules and configuration files needed to complete this challenge. If you plan to work locally, unpack the Resources.zip file on your workstation. If using Codespaces, the devcontainer will have the necessary dependencies pre-installed. + In this challenge, you will: -1. **Clone the Hackathon Repository** (contains all Terraform modules) +1. **Clone the Hackathon Repository** (contains all Terraform modules) if not using Codespaces 2. **Update Terraform variables** with your Azure subscription ID, principal IDs, and Confluent API keys 3. **Run Terraform** to provision the infrastructure 4. **Confirm data flows through connectors** @@ -84,33 +86,17 @@ In this challenge, you will: | **Confluent Cloud** | Kafka Cluster, Schema Registry, Kafka topics, Cosmos DB & Blob Source connectors, AI Search Sink connector | | **AI Agents / MCP** | Deployment of microservices + MCP servers that expose capabilities to agents | -### What you will verify - -* AI agents respond and can list the 8 departments -* Source connectors flow data from Cosmos DB and Blob Storage → Kafka topics -* Sink connector pushes data from Kafka → Azure AI Search - ## Success Criteria -To complete the challenge successfully, all of the following must be true: - -* Terraform deploys successfully** and resources appear in Azure Portal and Confluent Cloud -* Source connectors are live and pushing data** from Cosmos DB and Blob Storage into Kafka topics -* Sink connector is pushing data into Azure AI Search** (net sales + net inventory count topics) -* The MCP-powered AI agent can: - -* Respond when prompted -* State its name -* List all eight departments in the grocery store - -Completion checklist: +To complete this challenge successfully, you should be able to: -| Objective | Verification Step | -| --------------------------------- | -------------------------------------------- | -| Azure + Confluent resources exist | Terraform output + portal checks | -| Source connectors working | Messages visible in Kafka topics | -| Sink connector working | Index documents visible in Azure AI Search | -| Agent connected | Agent responds with name + lists departments | +- Verify Terraform deploys successfully and resources appear in Azure Portal and Confluent Cloud +- Verify source connectors are live and pushing data from Cosmos DB and Blob Storage into Kafka topics +- Verify sink connector is pushing data into Azure AI Search (net sales + net inventory count topics) +- Demonstrate the MCP-powered AI agent can: + - Respond when prompted + - State its name + - List all eight departments in the grocery store ## Learning Resources diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-01.md b/073-AIWithConfluentOnAzure/Student/Challenge-01.md index 7f9f46f554..ba21b88c71 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-01.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -11,25 +11,13 @@ In this challenge, you will create the streaming data pipeline that powers real- These tables will continuously update as new events stream into Kafka topics. ---- - ## Description During this challenge, you will: -1. Connect to the Apache Flink SQL editor in Confluent Cloud. -2. Create Flink tables mapped to existing Kafka topics: - - * `product_sku` - * `product_pricing` - * `product_departments` - * `purchases` - * `returns` - * `replenishments` -3. Write Flink SQL merge logic that continuously updates: - - * The `net_sales` table - * The `net_inventory_count` table +- Connect to the Apache Flink SQL editor in Confluent Cloud +- Create Flink tables mapped to existing Kafka topics: `product_sku`, `product_pricing`, `product_departments`, `purchases`, `returns`, and `replenishments` +- Write Flink SQL merge logic that continuously updates the `net_sales` table and the `net_inventory_count` table ### Required Merging Logic @@ -47,7 +35,6 @@ During this challenge, you will: * If the product belongs to the appliance department, returns add back to inventory. * Returns from all other departments are ignored (treated as perishable or damaged). -### Expected Outcome After your SQL statements are running, every new message streaming into Kafka should update: @@ -56,39 +43,22 @@ After your SQL statements are running, every new message streaming into Kafka sh in real time. ---- - ## Success Criteria -To complete this challenge successfully, the following must be true: - -* All Kafka topics listed above are mapped to Flink tables. -* Flink SQL merge statements for `net_sales` and `net_inventory_count` are created and running. -* Sales and inventory values update continuously as new messages stream in. -* Logic behaves correctly: +To complete this challenge successfully, you should be able to: - * Purchases increase net sales and decrease inventory. - * Replenishments increase inventory. - * Returns decrease net sales. - * Only appliance returns increase inventory count; all others are ignored. - -Completion checklist: - -* [ ] Flink tables created for all source Kafka topics -* [ ] Merge query running for `net_sales` -* [ ] Merge query running for `net_inventory_count` -* [ ] Inventory and sales update in real time during event flow - ---- +- Verify all Kafka topics listed above are mapped to Flink tables +- Verify Flink SQL merge statements for `net_sales` and `net_inventory_count` are created and running +- Verify sales and inventory values update continuously as new messages stream in +- Demonstrate logic behaves correctly: + - Purchases increase net sales and decrease inventory + - Replenishments increase inventory + - Returns decrease net sales + - Only appliance returns increase inventory count; all others are ignored ## Learning Resources -* Apache Flink SQL documentation - [Apache Flink Docs](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/overview/) - -* Confluent Cloud Flink quickstart - [Confluent Cloud Quickstart on Apache Flink](https://docs.confluent.io/cloud/current/flink/get-started/index.html) - -* Flink SQL merge and upsert concepts - [Flink SQL Data Processing with Merge](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) +- [Apache Flink SQL documentation](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/overview/) +- [Confluent Cloud Flink quickstart](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Flink SQL merge and upsert concepts](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-02.md b/073-AIWithConfluentOnAzure/Student/Challenge-02.md index 0ba4aa0852..cd70345059 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-02.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -15,52 +15,34 @@ In this challenge, you will assume the role of a supplier interacting with the A During this challenge, you will: -1. Log into the supplier agent experience. -2. Use the agent to query inventory levels across departments and product SKUs. -3. Replenish inventory by instructing the agent to update stock levels for specific SKUs or entire departments. -4. Verify in Azure AI Search that inventory data is being updated. -5. Confirm that the AI agent responds with accurate, real-time inventory values by querying the MCP service. +- Log into the supplier agent experience +- Use the agent to query inventory levels across departments and product SKUs +- Replenish inventory by instructing the agent to update stock levels for specific SKUs or entire departments +- Verify in Azure AI Search that inventory data is being updated +- Confirm that the AI agent responds with accurate, real-time inventory values by querying the MCP service Tasks to complete: -* View inventory levels for product SKUs within a specific department. -* View inventory level of a specific product SKU. -* Replenish inventory for a specific SKU. -* Replenish all SKUs within a department. -* Verify that inventory changes are reflected in Azure AI Search. -* Verify that the agent reflects accurate inventory levels based on the streaming data pipeline. +* View inventory levels for product SKUs within a specific department +* View inventory level of a specific product SKU +* Replenish inventory for a specific SKU +* Replenish all SKUs within a department +* Verify that inventory changes are reflected in Azure AI Search +* Verify that the agent reflects accurate inventory levels based on the streaming data pipeline ## Success Criteria -This challenge is complete when the following conditions are met: +To complete this challenge successfully, you should be able to: -* The supplier agent can display real-time inventory levels for any SKU. -* The supplier agent can display real-time inventory levels per department. -* Replenishment actions result in updated inventory values in the net inventory count table. -* Azure AI Search reflects the updated inventory counts for specific SKUs. -* The agent retrieves updated values from MCP services and responds accurately after inventory changes. - -Completion checklist: - -* [ ] Agent successfully retrieves inventory by SKU. -* [ ] Agent successfully retrieves inventory by department. -* [ ] Replenishment action updates inventory for an individual SKU. -* [ ] Replenishment action updates inventory for all SKUs within a department. -* [ ] Updated inventory values are reflected in Azure AI Search. -* [ ] Updated inventory values are returned correctly by the agent. - ---- +- Verify the supplier agent can display real-time inventory levels for any SKU +- Verify the supplier agent can display real-time inventory levels per department +- Demonstrate replenishment actions result in updated inventory values in the net inventory count table +- Verify Azure AI Search reflects the updated inventory counts for specific SKUs +- Verify the agent retrieves updated values from MCP services and responds accurately after inventory changes ## Learning Resources -* Working with Apache Flink SQL in Confluent Cloud - [https://docs.confluent.io/cloud/current/flink/get-started/index.html](https://docs.confluent.io/cloud/current/flink/get-started/index.html) - -* Using Azure AI Search as a real-time index - [https://learn.microsoft.com/azure/search/search-what-is-azure-search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) - -* Schema Registry and data contracts - [https://docs.confluent.io/platform/current/schema-registry/index.html](https://docs.confluent.io/platform/current/schema-registry/index.html) - -* Kafka Connect Source and Sink Connectors - [https://docs.confluent.io/cloud/current/connectors/index.html](https://docs.confluent.io/cloud/current/connectors/index.html) +- [Working with Apache Flink SQL in Confluent Cloud](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Using Azure AI Search as a real-time index](https://learn.microsoft.com/azure/search/search-what-is-azure-search) +- [Schema Registry and data contracts](https://docs.confluent.io/platform/current/schema-registry/index.html) +- [Kafka Connect Source and Sink Connectors](https://docs.confluent.io/cloud/current/connectors/index.html) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-03.md b/073-AIWithConfluentOnAzure/Student/Challenge-03.md index b5efc3c9ab..817b40874d 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-03.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -16,48 +16,33 @@ In this challenge, you will assume the role of a customer interacting with the c During this challenge, you will: -1. Log into the customer agent experience. -2. View inventory levels before purchasing items. -3. Perform a purchase action for one or more product SKUs. -4. Perform a return action for selected product SKUs. -5. Validate that inventory and sales data update in real time. +- Log into the customer agent experience +- View inventory levels before purchasing items +- Perform a purchase action for one or more product SKUs +- Perform a return action for selected product SKUs +- Validate that inventory and sales data update in real time Tasks to complete: -* View inventory levels for a specific product SKU before purchasing. -* Purchase product SKUs from different departments and record the quantities purchased. -* Return product SKUs from each department and record the quantities returned. -* After each purchase and return event, view the updated inventory to confirm changes. -* Ensure that inventory updates occur within a three-second window. +* View inventory levels for a specific product SKU before purchasing +* Purchase product SKUs from different departments and record the quantities purchased +* Return product SKUs from each department and record the quantities returned +* After each purchase and return event, view the updated inventory to confirm changes +* Ensure that inventory updates occur within a three-second window ## Success Criteria -This challenge is complete when the following conditions are met: +To complete this challenge successfully, you should be able to: -* The customer agent displays the inventory level of a SKU before a purchase. -* After a purchase, inventory is reduced and net sales are updated. -* After a return, inventory and net sales are updated following the business rules defined in the Flink merge logic. -* All inventory updates are visible within three seconds of the action being completed. -* The agent retrieves accurate, real-time values via MCP services backed by Azure AI Search. - -Completion checklist: - -* [ ] Customer can view inventory for a SKU before purchasing. -* [ ] Customer executes a purchase and observes updated values. -* [ ] Customer executes a return and observes updated values. -* [ ] Updated inventory and sales values are reflected within the required three-second threshold. -* [ ] Inventory and sales values shown by the agent match values in Azure AI Search and Flink. +- Verify the customer agent displays the inventory level of a SKU before a purchase +- Verify after a purchase, inventory is reduced and net sales are updated +- Verify after a return, inventory and net sales are updated following the business rules defined in the Flink merge logic +- Verify all inventory updates are visible within three seconds of the action being completed +- Verify the agent retrieves accurate, real-time values via MCP services backed by Azure AI Search ## Learning Resources -* Confluent Cloud Flink quickstart - [https://docs.confluent.io/cloud/current/flink/get-started/index.html](https://docs.confluent.io/cloud/current/flink/get-started/index.html) - -* Event processing and upsert patterns in Apache Flink - [https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) - -* Azure AI Search indexing concepts - [https://learn.microsoft.com/azure/search/search-what-is-azure-search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) - -* Kafka event streaming fundamentals - [https://kafka.apache.org/documentation/](https://kafka.apache.org/documentation/) \ No newline at end of file +- [Confluent Cloud Flink quickstart](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Event processing and upsert patterns in Apache Flink](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) +- [Azure AI Search indexing concepts](https://learn.microsoft.com/azure/search/search-what-is-azure-search) +- [Kafka event streaming fundamentals](https://kafka.apache.org/documentation/) \ No newline at end of file diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-04.md b/073-AIWithConfluentOnAzure/Student/Challenge-04.md index 68eea78a47..a304959fbf 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-04.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -18,51 +18,34 @@ This challenge requires interaction across multiple personas. You will switch be During this challenge, you will: -1. Log into the employee agent experience. -2. Query real-time inventory and cumulative transaction metrics. -3. Use other personas (customer and supplier) to trigger purchase, return, and replenishment events. -4. Confirm that the employee agent responds with accurate values based on the updated data pipeline. +- Log into the employee agent experience +- Query real-time inventory and cumulative transaction metrics +- Use other personas (customer and supplier) to trigger purchase, return, and replenishment events +- Confirm that the employee agent responds with accurate values based on the updated data pipeline Tasks to complete: -* View inventory levels for any product SKU. -* View inventory levels for all product SKUs within a department. -* Retrieve cumulative purchase units for any SKU after a purchase event. -* Retrieve cumulative return units for any SKU after a return event. -* Retrieve cumulative replenishment units for any SKU after a supplier replenishment event. -* Retrieve the net inventory count for any SKU after any event. -* Retrieve the net sales numbers for any SKU after events are finalized. +* View inventory levels for any product SKU +* View inventory levels for all product SKUs within a department +* Retrieve cumulative purchase units for any SKU after a purchase event +* Retrieve cumulative return units for any SKU after a return event +* Retrieve cumulative replenishment units for any SKU after a supplier replenishment event +* Retrieve the net inventory count for any SKU after any event +* Retrieve the net sales numbers for any SKU after events are finalized ## Success Criteria -This challenge is complete when the following conditions are met: +To complete this challenge successfully, you should be able to: -* The employee agent can display inventory levels for individual SKUs. -* The employee agent can display inventory levels for all SKUs in a department. -* Cumulative purchase, return, and replenishment values for any SKU are retrieved accurately. -* The agent provides accurate net inventory counts and net sales values after transactions. -* Inventory and sales values shown by the agent match what is observed in Azure AI Search and Flink output. - -Completion checklist: - -* [ ] Employee agent retrieves current inventory for a SKU. -* [ ] Employee agent retrieves inventory for a department. -* [ ] Cumulative purchase units update after customer purchase events. -* [ ] Cumulative return units update after customer return events. -* [ ] Cumulative replenishment units update after supplier replenishment events. -* [ ] Net inventory count is accurate after each event type. -* [ ] Net sales values update correctly after each event type. +- Verify the employee agent can display inventory levels for individual SKUs +- Verify the employee agent can display inventory levels for all SKUs in a department +- Verify cumulative purchase, return, and replenishment values for any SKU are retrieved accurately +- Verify the agent provides accurate net inventory counts and net sales values after transactions +- Verify inventory and sales values shown by the agent match what is observed in Azure AI Search and Flink output ## Learning Resources -* Confluent Cloud Flink quickstart - [https://docs.confluent.io/cloud/current/flink/get-started/index.html](https://docs.confluent.io/cloud/current/flink/get-started/index.html) - -* Flink SQL upsert and aggregate patterns - [https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) - -* Azure AI Search indexing concepts - [https://learn.microsoft.com/azure/search/search-what-is-azure-search](https://learn.microsoft.com/azure/search/search-what-is-azure-search) - -* Kafka event streaming fundamentals - [https://kafka.apache.org/documentation/](https://kafka.apache.org/documentation/) \ No newline at end of file +- [Confluent Cloud Flink quickstart](https://docs.confluent.io/cloud/current/flink/get-started/index.html) +- [Flink SQL upsert and aggregate patterns](https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/table/sql/queries/insert/) +- [Azure AI Search indexing concepts](https://learn.microsoft.com/azure/search/search-what-is-azure-search) +- [Kafka event streaming fundamentals](https://kafka.apache.org/documentation/) \ No newline at end of file From 7583b7be6ac76604183dab3daca5965ec124b776 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Wed, 12 Nov 2025 17:00:03 -0800 Subject: [PATCH 21/32] Updating challenge 1 intro --- 073-AIWithConfluentOnAzure/Student/Challenge-01.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-01.md b/073-AIWithConfluentOnAzure/Student/Challenge-01.md index ba21b88c71..cf89f19c72 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-01.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-01.md @@ -4,12 +4,14 @@ ## Introduction -In this challenge, you will create the streaming data pipeline that powers real-time inventory and sales updates for the online grocery store. Using Apache Flink on Confluent Cloud, you will map Kafka topics to Flink tables and merge multiple data streams (purchases, returns, pricing, departments, and replenishments) into two aggregated output tables: +Welcome to the command center of a modern online grocery store. Every second, customers are buying, returning, and restocking items. Our goal is to build a real-time streaming pipeline that tracks every penny earned and every item in stock as it happens. -* `net_sales` -* `net_inventory_count` +Using Apache Flink on Confluent Cloud, you'll merge multiple data streams (purchases, returns, pricing, departments, and replenishments) into two critical business metrics: -These tables will continuously update as new events stream into Kafka topics. +* `net_sales` - Real-time revenue tracking +* `net_inventory_count` - Live inventory levels + +Every event streaming into Kafka will instantly update your business metrics in real-time. ## Description From 39008489dde6fc76c16c94a1bba6355aa7de246c Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Wed, 12 Nov 2025 19:33:29 -0800 Subject: [PATCH 22/32] Updating challenge 2-4 --- .../Student/Challenge-02.md | 20 ++++++------------- .../Student/Challenge-03.md | 19 ++++++------------ .../Student/Challenge-04.md | 19 +++++++----------- 3 files changed, 19 insertions(+), 39 deletions(-) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-02.md b/073-AIWithConfluentOnAzure/Student/Challenge-02.md index cd70345059..2ab96e7184 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-02.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-02.md @@ -15,20 +15,12 @@ In this challenge, you will assume the role of a supplier interacting with the A During this challenge, you will: -- Log into the supplier agent experience -- Use the agent to query inventory levels across departments and product SKUs -- Replenish inventory by instructing the agent to update stock levels for specific SKUs or entire departments -- Verify in Azure AI Search that inventory data is being updated -- Confirm that the AI agent responds with accurate, real-time inventory values by querying the MCP service - -Tasks to complete: - -* View inventory levels for product SKUs within a specific department -* View inventory level of a specific product SKU -* Replenish inventory for a specific SKU -* Replenish all SKUs within a department -* Verify that inventory changes are reflected in Azure AI Search -* Verify that the agent reflects accurate inventory levels based on the streaming data pipeline +- Log into the supplier agent experience and explore its capabilities +- View inventory levels for product SKUs within specific departments +- View inventory levels for individual product SKUs +- Replenish inventory for specific SKUs or entire departments through the agent +- Verify that inventory changes are reflected in Azure AI Search +- Confirm that the AI agent responds with accurate, real-time inventory values from the streaming data pipeline ## Success Criteria diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-03.md b/073-AIWithConfluentOnAzure/Student/Challenge-03.md index 817b40874d..d50cf672d5 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-03.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-03.md @@ -16,19 +16,12 @@ In this challenge, you will assume the role of a customer interacting with the c During this challenge, you will: -- Log into the customer agent experience -- View inventory levels before purchasing items -- Perform a purchase action for one or more product SKUs -- Perform a return action for selected product SKUs -- Validate that inventory and sales data update in real time - -Tasks to complete: - -* View inventory levels for a specific product SKU before purchasing -* Purchase product SKUs from different departments and record the quantities purchased -* Return product SKUs from each department and record the quantities returned -* After each purchase and return event, view the updated inventory to confirm changes -* Ensure that inventory updates occur within a three-second window +- Log into the customer agent experience and explore its capabilities +- View inventory levels for specific product SKUs before making purchases +- Purchase product SKUs from different departments and record the quantities purchased +- Return product SKUs from each department and record the quantities returned +- Validate that inventory and sales data update in real time after each action +- Ensure that all inventory updates are visible within a three-second window ## Success Criteria diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-04.md b/073-AIWithConfluentOnAzure/Student/Challenge-04.md index a304959fbf..86f1f56d00 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-04.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -18,20 +18,15 @@ This challenge requires interaction across multiple personas. You will switch be During this challenge, you will: -- Log into the employee agent experience -- Query real-time inventory and cumulative transaction metrics +- Log into the employee agent experience and explore its comprehensive capabilities +- Query real-time inventory and cumulative transaction metrics for any product SKU +- View inventory levels for individual SKUs and entire departments - Use other personas (customer and supplier) to trigger purchase, return, and replenishment events -- Confirm that the employee agent responds with accurate values based on the updated data pipeline +- Retrieve cumulative purchase, return, and replenishment units for any SKU after events occur +- Confirm that the employee agent responds with accurate net inventory counts and net sales values +- Verify that all data matches what is observed in Azure AI Search and Flink output -Tasks to complete: - -* View inventory levels for any product SKU -* View inventory levels for all product SKUs within a department -* Retrieve cumulative purchase units for any SKU after a purchase event -* Retrieve cumulative return units for any SKU after a return event -* Retrieve cumulative replenishment units for any SKU after a supplier replenishment event -* Retrieve the net inventory count for any SKU after any event -* Retrieve the net sales numbers for any SKU after events are finalized +This challenge requires interaction across multiple personas. You will switch between customer, supplier, and employee tabs or windows to simulate real-world concurrent activity. Each action triggers updates to the net inventory count and net sales tables, and the employee agent should always return accurate, real-time data. ## Success Criteria From aab88169adbabaffab3d5b6bc08b786b4e219330 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Thu, 13 Nov 2025 10:00:21 -0800 Subject: [PATCH 23/32] Update challenge 00 description --- 073-AIWithConfluentOnAzure/Student/Challenge-00.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-00.md b/073-AIWithConfluentOnAzure/Student/Challenge-00.md index c0f25516cd..030a94ca45 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-00.md +++ b/073-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -73,7 +73,7 @@ Your coach will provide you with a Resources.zip file (or access to a Codespaces In this challenge, you will: -1. **Clone the Hackathon Repository** (contains all Terraform modules) if not using Codespaces +1. **Locate the Terraform modules** in the Resources folder (provided via Resources.zip or Codespaces) 2. **Update Terraform variables** with your Azure subscription ID, principal IDs, and Confluent API keys 3. **Run Terraform** to provision the infrastructure 4. **Confirm data flows through connectors** From e8f007f38cb068c008916de21fe8e2da92b3ea8c Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Tue, 3 Mar 2026 16:02:12 -0800 Subject: [PATCH 24/32] Updating to 074 --- .../devcontainer.json | 2 +- .../WTHAuthor.chatmode.md | 0 .../Coach/Solution-00.md | 20 ----- .../Coach/Solution-01.md | 20 ----- .../Coach/Solution-02.md | 20 ----- .../Coach/Solution-03.md | 20 ----- .../Coach/Solution-04.md | 20 ----- .../Coach/Lectures.pptx | Bin .../Coach/README.md | 42 ++++----- .../Coach/Solution-00.md | 18 ++++ .../Coach/Solution-01.md | 21 +++++ .../Coach/Solution-02.md | 14 +++ .../Coach/Solution-03.md | 15 ++++ .../Coach/Solution-04.md | 16 ++++ .../Coach/Solutions/.gitkeep | 0 .../Coach/Solutions/flink-sql/README.md | 0 .../Solutions/flink-sql/data_pipeline-ddl.sql | 0 .../Solutions/flink-sql/data_pipeline-dml.sql | 0 .../Solutions/flink-sql/ddl-sink-tables.sql | 0 .../Solutions/flink-sql/ddl-source-tables.sql | 0 .../flink-sql/drafts/departments.sql | 0 .../flink-sql/drafts/departments_flat.sql | 0 .../flink-sql/drafts/flat_tables.sql | 0 .../flink-sql/drafts/product_skus.sql | 0 .../Solutions/flink-sql/drafts/purchases.sql | 0 .../flink-sql/drafts/replenishments.sql | 0 .../flink-sql/drafts/retail_tables.sql | 0 .../Solutions/flink-sql/drafts/returns.sql | 0 .../check_resources_status.sh | 0 .../maintenance_scripts/environment-azure.sh | 0 .../environment-confluent.sh | 0 .../fix_azure_blob_store.sh | 0 .../fix_azure_cosmos_db.sh | 0 .../README.md | 25 ++++-- .../Student/Challenge-00.md | 84 ++++++------------ .../Student/Challenge-01.md | 0 .../Student/Challenge-02.md | 0 .../Student/Challenge-03.md | 0 .../Student/Challenge-04.md | 2 - .../Student/Resources/.gitkeep | 0 .../agentic-application/.dockerignore | 0 .../agentic-application/.env.sh.example | 0 .../agentic-application/DOCKER_BUILDS.md | 0 .../agentic-application/Dockerfile.base | 0 .../agentic-application/Dockerfile.customer | 0 .../agentic-application/Dockerfile.employee | 0 .../agentic-application/Dockerfile.inventory | 0 .../Dockerfile.replenishment | 0 .../agentic-application/Dockerfile.shopping | 0 .../agentic-application/Dockerfile.supplier | 0 .../Resources/agentic-application/LICENSE | 0 .../Resources/agentic-application/NOTES.md | 0 .../Resources/agentic-application/README.md | 0 .../RUNNING_THE_APPLICATION.md | 0 .../agent_customer_experience.py | 0 .../agent_employee_experience.py | 0 .../agent_supplier_experience.py | 0 .../contoso_retail_application/__init__.py | 0 .../agent_graphs.py | 0 .../ai_foundry_setup.py | 0 .../data_access_objects.py | 0 .../contoso_retail_application/models.py | 0 .../service_configuration_inventory.py | 0 .../service_configuration_replenishment.py | 0 .../service_configuration_shopping.py | 0 .../static_dataset.py | 0 .../contoso_retail_application/utils.py | 0 .../entrypoints/entrypoint.agent-customer.sh | 0 .../entrypoints/entrypoint.agent-employee.sh | 0 .../entrypoints/entrypoint.agent-supplier.sh | 0 .../entrypoints/entrypoint.mcp-inventory.sh | 0 .../entrypoint.mcp-replenishment.sh | 0 .../entrypoints/entrypoint.mcp-shopping.sh | 0 .../Resources/agentic-application/main.py | 0 .../agentic-application/mcp_service.py | 0 .../agentic-application/pyproject.toml | 0 .../tests/test_replenishment.py | 0 .../agentic-application/tests/test_sales.py | 0 .../Resources/agentic-application/uv.lock | 0 .../ai-search-schemas/departments_flat.json | 0 .../ai-search-schemas/net_sales.json | 0 .../ai-search-schemas/product_inventory.json | 0 .../Resources/azure-setup-create-indices.sh | 0 .../Resources/compose/docker-compose.yml | 0 .../shared_environment_variables.env.example | 0 .../Student/Resources/confluent-setup-cli.sh | 0 .../confluent-setup-create-connectors.sh | 0 .../confluent-setup-create-topics.sh | 0 .../confluent-setup-delete-connectors.sh | 0 .../confluent-setup-delete-schemas.sh | 0 .../confluent-setup-delete-topics.sh | 0 .../Resources/confluent-setup-flink-sql.sh | 0 ...fluent-setup-populate-connector-configs.sh | 0 ...onfluent-setup-populate-connector-reset.sh | 0 .../ai_search_departments_flat.example.json | 0 .../ai_search_net_sales.example.json | 0 .../ai_search_product_inventory.example.json | 0 .../azure_blob_departments.example.json | 0 .../azure_blob_product_pricing.example.json | 0 .../azure_blob_product_skus.example.json | 0 .../cosmos_db_purchases.example.json | 0 .../cosmos_db_replenishments.example.json | 0 .../cosmos_db_returns.example.json | 0 .../Student/Resources/retail_store/README.md | 0 .../UPLOADING_BLOB_STORE_CONTENTS.md | 0 .../retail_store/azure_blob_upload.sh | 0 .../retail_store/departments/appliance.json | 0 .../retail_store/departments/cleaning.json | 0 .../retail_store/departments/dairy.json | 0 .../retail_store/departments/deli.json | 0 .../retail_store/departments/meat.json | 0 .../retail_store/departments/pharmacy.json | 0 .../retail_store/departments/produce.json | 0 .../schemas/departments-key.schema | 0 .../schemas/departments-value.schema | 0 .../retail_store/departments/seafood.json | 0 .../departments_flat/appliance.json | 0 .../departments_flat/cleaning.json | 0 .../retail_store/departments_flat/dairy.json | 0 .../retail_store/departments_flat/deli.json | 0 .../retail_store/departments_flat/meat.json | 0 .../departments_flat/pharmacy.json | 0 .../departments_flat/produce.json | 0 .../schemas/departments_flat-key.schema | 0 .../schemas/departments_flat-value.schema | 0 .../departments_flat/seafood.json | 0 .../Resources/retail_store/net_sales/101.json | 0 .../net_sales/schemas/net_sales-key.schema | 0 .../net_sales/schemas/net_sales-value.schema | 0 .../retail_store/product_inventory/101.json | 0 .../retail_store/product_inventory/102.json | 0 .../schemas/product_inventory-key.schema | 0 .../schemas/product_inventory-value.schema | 0 .../retail_store/product_pricing/101.json | 0 .../retail_store/product_pricing/102.json | 0 .../retail_store/product_pricing/103.json | 0 .../retail_store/product_pricing/104.json | 0 .../retail_store/product_pricing/105.json | 0 .../retail_store/product_pricing/106.json | 0 .../retail_store/product_pricing/107.json | 0 .../retail_store/product_pricing/108.json | 0 .../retail_store/product_pricing/109.json | 0 .../retail_store/product_pricing/110.json | 0 .../retail_store/product_pricing/111.json | 0 .../retail_store/product_pricing/112.json | 0 .../retail_store/product_pricing/113.json | 0 .../retail_store/product_pricing/114.json | 0 .../retail_store/product_pricing/115.json | 0 .../retail_store/product_pricing/116.json | 0 .../retail_store/product_pricing/117.json | 0 .../retail_store/product_pricing/118.json | 0 .../retail_store/product_pricing/119.json | 0 .../retail_store/product_pricing/120.json | 0 .../retail_store/product_pricing/121.json | 0 .../retail_store/product_pricing/122.json | 0 .../retail_store/product_pricing/123.json | 0 .../retail_store/product_pricing/124.json | 0 .../retail_store/product_pricing/125.json | 0 .../retail_store/product_pricing/201.json | 0 .../retail_store/product_pricing/202.json | 0 .../retail_store/product_pricing/203.json | 0 .../retail_store/product_pricing/204.json | 0 .../retail_store/product_pricing/205.json | 0 .../retail_store/product_pricing/206.json | 0 .../retail_store/product_pricing/207.json | 0 .../retail_store/product_pricing/208.json | 0 .../retail_store/product_pricing/209.json | 0 .../retail_store/product_pricing/210.json | 0 .../retail_store/product_pricing/211.json | 0 .../retail_store/product_pricing/212.json | 0 .../retail_store/product_pricing/213.json | 0 .../retail_store/product_pricing/214.json | 0 .../retail_store/product_pricing/215.json | 0 .../retail_store/product_pricing/216.json | 0 .../retail_store/product_pricing/217.json | 0 .../retail_store/product_pricing/218.json | 0 .../retail_store/product_pricing/219.json | 0 .../retail_store/product_pricing/220.json | 0 .../retail_store/product_pricing/221.json | 0 .../retail_store/product_pricing/222.json | 0 .../retail_store/product_pricing/223.json | 0 .../retail_store/product_pricing/224.json | 0 .../retail_store/product_pricing/225.json | 0 .../retail_store/product_pricing/301.json | 0 .../retail_store/product_pricing/302.json | 0 .../retail_store/product_pricing/303.json | 0 .../retail_store/product_pricing/304.json | 0 .../retail_store/product_pricing/305.json | 0 .../retail_store/product_pricing/306.json | 0 .../retail_store/product_pricing/307.json | 0 .../retail_store/product_pricing/308.json | 0 .../retail_store/product_pricing/309.json | 0 .../retail_store/product_pricing/310.json | 0 .../retail_store/product_pricing/311.json | 0 .../retail_store/product_pricing/312.json | 0 .../retail_store/product_pricing/313.json | 0 .../retail_store/product_pricing/314.json | 0 .../retail_store/product_pricing/315.json | 0 .../retail_store/product_pricing/316.json | 0 .../retail_store/product_pricing/317.json | 0 .../retail_store/product_pricing/318.json | 0 .../retail_store/product_pricing/319.json | 0 .../retail_store/product_pricing/320.json | 0 .../retail_store/product_pricing/321.json | 0 .../retail_store/product_pricing/322.json | 0 .../retail_store/product_pricing/323.json | 0 .../retail_store/product_pricing/324.json | 0 .../retail_store/product_pricing/325.json | 0 .../retail_store/product_pricing/401.json | 0 .../retail_store/product_pricing/402.json | 0 .../retail_store/product_pricing/403.json | 0 .../retail_store/product_pricing/404.json | 0 .../retail_store/product_pricing/405.json | 0 .../retail_store/product_pricing/406.json | 0 .../retail_store/product_pricing/407.json | 0 .../retail_store/product_pricing/408.json | 0 .../retail_store/product_pricing/409.json | 0 .../retail_store/product_pricing/410.json | 0 .../retail_store/product_pricing/411.json | 0 .../retail_store/product_pricing/412.json | 0 .../retail_store/product_pricing/413.json | 0 .../retail_store/product_pricing/414.json | 0 .../retail_store/product_pricing/415.json | 0 .../retail_store/product_pricing/416.json | 0 .../retail_store/product_pricing/417.json | 0 .../retail_store/product_pricing/418.json | 0 .../retail_store/product_pricing/419.json | 0 .../retail_store/product_pricing/420.json | 0 .../retail_store/product_pricing/421.json | 0 .../retail_store/product_pricing/422.json | 0 .../retail_store/product_pricing/423.json | 0 .../retail_store/product_pricing/424.json | 0 .../retail_store/product_pricing/425.json | 0 .../retail_store/product_pricing/501.json | 0 .../retail_store/product_pricing/502.json | 0 .../retail_store/product_pricing/503.json | 0 .../retail_store/product_pricing/504.json | 0 .../retail_store/product_pricing/505.json | 0 .../retail_store/product_pricing/506.json | 0 .../retail_store/product_pricing/507.json | 0 .../retail_store/product_pricing/508.json | 0 .../retail_store/product_pricing/509.json | 0 .../retail_store/product_pricing/510.json | 0 .../retail_store/product_pricing/511.json | 0 .../retail_store/product_pricing/512.json | 0 .../retail_store/product_pricing/513.json | 0 .../retail_store/product_pricing/514.json | 0 .../retail_store/product_pricing/515.json | 0 .../retail_store/product_pricing/516.json | 0 .../retail_store/product_pricing/517.json | 0 .../retail_store/product_pricing/518.json | 0 .../retail_store/product_pricing/519.json | 0 .../retail_store/product_pricing/520.json | 0 .../retail_store/product_pricing/521.json | 0 .../retail_store/product_pricing/522.json | 0 .../retail_store/product_pricing/523.json | 0 .../retail_store/product_pricing/524.json | 0 .../retail_store/product_pricing/525.json | 0 .../retail_store/product_pricing/601.json | 0 .../retail_store/product_pricing/602.json | 0 .../retail_store/product_pricing/603.json | 0 .../retail_store/product_pricing/604.json | 0 .../retail_store/product_pricing/605.json | 0 .../retail_store/product_pricing/606.json | 0 .../retail_store/product_pricing/607.json | 0 .../retail_store/product_pricing/608.json | 0 .../retail_store/product_pricing/609.json | 0 .../retail_store/product_pricing/610.json | 0 .../retail_store/product_pricing/611.json | 0 .../retail_store/product_pricing/612.json | 0 .../retail_store/product_pricing/613.json | 0 .../retail_store/product_pricing/614.json | 0 .../retail_store/product_pricing/615.json | 0 .../retail_store/product_pricing/616.json | 0 .../retail_store/product_pricing/617.json | 0 .../retail_store/product_pricing/618.json | 0 .../retail_store/product_pricing/619.json | 0 .../retail_store/product_pricing/620.json | 0 .../retail_store/product_pricing/621.json | 0 .../retail_store/product_pricing/622.json | 0 .../retail_store/product_pricing/623.json | 0 .../retail_store/product_pricing/624.json | 0 .../retail_store/product_pricing/625.json | 0 .../retail_store/product_pricing/701.json | 0 .../retail_store/product_pricing/702.json | 0 .../retail_store/product_pricing/703.json | 0 .../retail_store/product_pricing/704.json | 0 .../retail_store/product_pricing/705.json | 0 .../retail_store/product_pricing/706.json | 0 .../retail_store/product_pricing/707.json | 0 .../retail_store/product_pricing/708.json | 0 .../retail_store/product_pricing/709.json | 0 .../retail_store/product_pricing/710.json | 0 .../retail_store/product_pricing/711.json | 0 .../retail_store/product_pricing/712.json | 0 .../retail_store/product_pricing/713.json | 0 .../retail_store/product_pricing/714.json | 0 .../retail_store/product_pricing/715.json | 0 .../retail_store/product_pricing/716.json | 0 .../retail_store/product_pricing/717.json | 0 .../retail_store/product_pricing/718.json | 0 .../retail_store/product_pricing/719.json | 0 .../retail_store/product_pricing/720.json | 0 .../retail_store/product_pricing/721.json | 0 .../retail_store/product_pricing/722.json | 0 .../retail_store/product_pricing/723.json | 0 .../retail_store/product_pricing/724.json | 0 .../retail_store/product_pricing/725.json | 0 .../retail_store/product_pricing/801.json | 0 .../retail_store/product_pricing/802.json | 0 .../retail_store/product_pricing/803.json | 0 .../retail_store/product_pricing/804.json | 0 .../retail_store/product_pricing/805.json | 0 .../retail_store/product_pricing/806.json | 0 .../retail_store/product_pricing/807.json | 0 .../retail_store/product_pricing/808.json | 0 .../retail_store/product_pricing/809.json | 0 .../retail_store/product_pricing/810.json | 0 .../retail_store/product_pricing/811.json | 0 .../retail_store/product_pricing/812.json | 0 .../retail_store/product_pricing/813.json | 0 .../retail_store/product_pricing/814.json | 0 .../retail_store/product_pricing/815.json | 0 .../retail_store/product_pricing/816.json | 0 .../retail_store/product_pricing/817.json | 0 .../retail_store/product_pricing/818.json | 0 .../retail_store/product_pricing/819.json | 0 .../retail_store/product_pricing/820.json | 0 .../retail_store/product_pricing/821.json | 0 .../retail_store/product_pricing/822.json | 0 .../retail_store/product_pricing/823.json | 0 .../retail_store/product_pricing/824.json | 0 .../retail_store/product_pricing/825.json | 0 .../schemas/product_pricing-key.schema | 0 .../schemas/product_pricing-value.schema | 0 .../retail_store/product_skus/101.json | 0 .../retail_store/product_skus/102.json | 0 .../retail_store/product_skus/103.json | 0 .../retail_store/product_skus/104.json | 0 .../retail_store/product_skus/105.json | 0 .../retail_store/product_skus/106.json | 0 .../retail_store/product_skus/107.json | 0 .../retail_store/product_skus/108.json | 0 .../retail_store/product_skus/109.json | 0 .../retail_store/product_skus/110.json | 0 .../retail_store/product_skus/111.json | 0 .../retail_store/product_skus/112.json | 0 .../retail_store/product_skus/113.json | 0 .../retail_store/product_skus/114.json | 0 .../retail_store/product_skus/115.json | 0 .../retail_store/product_skus/116.json | 0 .../retail_store/product_skus/117.json | 0 .../retail_store/product_skus/118.json | 0 .../retail_store/product_skus/119.json | 0 .../retail_store/product_skus/120.json | 0 .../retail_store/product_skus/121.json | 0 .../retail_store/product_skus/122.json | 0 .../retail_store/product_skus/123.json | 0 .../retail_store/product_skus/124.json | 0 .../retail_store/product_skus/125.json | 0 .../retail_store/product_skus/201.json | 0 .../retail_store/product_skus/202.json | 0 .../retail_store/product_skus/203.json | 0 .../retail_store/product_skus/204.json | 0 .../retail_store/product_skus/205.json | 0 .../retail_store/product_skus/206.json | 0 .../retail_store/product_skus/207.json | 0 .../retail_store/product_skus/208.json | 0 .../retail_store/product_skus/209.json | 0 .../retail_store/product_skus/210.json | 0 .../retail_store/product_skus/211.json | 0 .../retail_store/product_skus/212.json | 0 .../retail_store/product_skus/213.json | 0 .../retail_store/product_skus/214.json | 0 .../retail_store/product_skus/215.json | 0 .../retail_store/product_skus/216.json | 0 .../retail_store/product_skus/217.json | 0 .../retail_store/product_skus/218.json | 0 .../retail_store/product_skus/219.json | 0 .../retail_store/product_skus/220.json | 0 .../retail_store/product_skus/221.json | 0 .../retail_store/product_skus/222.json | 0 .../retail_store/product_skus/223.json | 0 .../retail_store/product_skus/224.json | 0 .../retail_store/product_skus/225.json | 0 .../retail_store/product_skus/301.json | 0 .../retail_store/product_skus/302.json | 0 .../retail_store/product_skus/303.json | 0 .../retail_store/product_skus/304.json | 0 .../retail_store/product_skus/305.json | 0 .../retail_store/product_skus/306.json | 0 .../retail_store/product_skus/307.json | 0 .../retail_store/product_skus/308.json | 0 .../retail_store/product_skus/309.json | 0 .../retail_store/product_skus/310.json | 0 .../retail_store/product_skus/311.json | 0 .../retail_store/product_skus/312.json | 0 .../retail_store/product_skus/313.json | 0 .../retail_store/product_skus/314.json | 0 .../retail_store/product_skus/315.json | 0 .../retail_store/product_skus/316.json | 0 .../retail_store/product_skus/317.json | 0 .../retail_store/product_skus/318.json | 0 .../retail_store/product_skus/319.json | 0 .../retail_store/product_skus/320.json | 0 .../retail_store/product_skus/321.json | 0 .../retail_store/product_skus/322.json | 0 .../retail_store/product_skus/323.json | 0 .../retail_store/product_skus/324.json | 0 .../retail_store/product_skus/325.json | 0 .../retail_store/product_skus/401.json | 0 .../retail_store/product_skus/402.json | 0 .../retail_store/product_skus/403.json | 0 .../retail_store/product_skus/404.json | 0 .../retail_store/product_skus/405.json | 0 .../retail_store/product_skus/406.json | 0 .../retail_store/product_skus/407.json | 0 .../retail_store/product_skus/408.json | 0 .../retail_store/product_skus/409.json | 0 .../retail_store/product_skus/410.json | 0 .../retail_store/product_skus/411.json | 0 .../retail_store/product_skus/412.json | 0 .../retail_store/product_skus/413.json | 0 .../retail_store/product_skus/414.json | 0 .../retail_store/product_skus/415.json | 0 .../retail_store/product_skus/416.json | 0 .../retail_store/product_skus/417.json | 0 .../retail_store/product_skus/418.json | 0 .../retail_store/product_skus/419.json | 0 .../retail_store/product_skus/420.json | 0 .../retail_store/product_skus/421.json | 0 .../retail_store/product_skus/422.json | 0 .../retail_store/product_skus/423.json | 0 .../retail_store/product_skus/424.json | 0 .../retail_store/product_skus/425.json | 0 .../retail_store/product_skus/501.json | 0 .../retail_store/product_skus/502.json | 0 .../retail_store/product_skus/503.json | 0 .../retail_store/product_skus/504.json | 0 .../retail_store/product_skus/505.json | 0 .../retail_store/product_skus/506.json | 0 .../retail_store/product_skus/507.json | 0 .../retail_store/product_skus/508.json | 0 .../retail_store/product_skus/509.json | 0 .../retail_store/product_skus/510.json | 0 .../retail_store/product_skus/511.json | 0 .../retail_store/product_skus/512.json | 0 .../retail_store/product_skus/513.json | 0 .../retail_store/product_skus/514.json | 0 .../retail_store/product_skus/515.json | 0 .../retail_store/product_skus/516.json | 0 .../retail_store/product_skus/517.json | 0 .../retail_store/product_skus/518.json | 0 .../retail_store/product_skus/519.json | 0 .../retail_store/product_skus/520.json | 0 .../retail_store/product_skus/521.json | 0 .../retail_store/product_skus/522.json | 0 .../retail_store/product_skus/523.json | 0 .../retail_store/product_skus/524.json | 0 .../retail_store/product_skus/525.json | 0 .../retail_store/product_skus/601.json | 0 .../retail_store/product_skus/602.json | 0 .../retail_store/product_skus/603.json | 0 .../retail_store/product_skus/604.json | 0 .../retail_store/product_skus/605.json | 0 .../retail_store/product_skus/606.json | 0 .../retail_store/product_skus/607.json | 0 .../retail_store/product_skus/608.json | 0 .../retail_store/product_skus/609.json | 0 .../retail_store/product_skus/610.json | 0 .../retail_store/product_skus/611.json | 0 .../retail_store/product_skus/612.json | 0 .../retail_store/product_skus/613.json | 0 .../retail_store/product_skus/614.json | 0 .../retail_store/product_skus/615.json | 0 .../retail_store/product_skus/616.json | 0 .../retail_store/product_skus/617.json | 0 .../retail_store/product_skus/618.json | 0 .../retail_store/product_skus/619.json | 0 .../retail_store/product_skus/620.json | 0 .../retail_store/product_skus/621.json | 0 .../retail_store/product_skus/622.json | 0 .../retail_store/product_skus/623.json | 0 .../retail_store/product_skus/624.json | 0 .../retail_store/product_skus/625.json | 0 .../retail_store/product_skus/701.json | 0 .../retail_store/product_skus/702.json | 0 .../retail_store/product_skus/703.json | 0 .../retail_store/product_skus/704.json | 0 .../retail_store/product_skus/705.json | 0 .../retail_store/product_skus/706.json | 0 .../retail_store/product_skus/707.json | 0 .../retail_store/product_skus/708.json | 0 .../retail_store/product_skus/709.json | 0 .../retail_store/product_skus/710.json | 0 .../retail_store/product_skus/711.json | 0 .../retail_store/product_skus/712.json | 0 .../retail_store/product_skus/713.json | 0 .../retail_store/product_skus/714.json | 0 .../retail_store/product_skus/715.json | 0 .../retail_store/product_skus/716.json | 0 .../retail_store/product_skus/717.json | 0 .../retail_store/product_skus/718.json | 0 .../retail_store/product_skus/719.json | 0 .../retail_store/product_skus/720.json | 0 .../retail_store/product_skus/721.json | 0 .../retail_store/product_skus/722.json | 0 .../retail_store/product_skus/723.json | 0 .../retail_store/product_skus/724.json | 0 .../retail_store/product_skus/725.json | 0 .../retail_store/product_skus/801.json | 0 .../retail_store/product_skus/802.json | 0 .../retail_store/product_skus/803.json | 0 .../retail_store/product_skus/804.json | 0 .../retail_store/product_skus/805.json | 0 .../retail_store/product_skus/806.json | 0 .../retail_store/product_skus/807.json | 0 .../retail_store/product_skus/808.json | 0 .../retail_store/product_skus/809.json | 0 .../retail_store/product_skus/810.json | 0 .../retail_store/product_skus/811.json | 0 .../retail_store/product_skus/812.json | 0 .../retail_store/product_skus/813.json | 0 .../retail_store/product_skus/814.json | 0 .../retail_store/product_skus/815.json | 0 .../retail_store/product_skus/816.json | 0 .../retail_store/product_skus/817.json | 0 .../retail_store/product_skus/818.json | 0 .../retail_store/product_skus/819.json | 0 .../retail_store/product_skus/820.json | 0 .../retail_store/product_skus/821.json | 0 .../retail_store/product_skus/822.json | 0 .../retail_store/product_skus/823.json | 0 .../retail_store/product_skus/824.json | 0 .../retail_store/product_skus/825.json | 0 .../schemas/product_skus-key.schema | 0 .../schemas/product_skus-value.schema | 0 .../retail_store/purchases/1000.json | 0 .../retail_store/purchases/1001.json | 0 .../retail_store/purchases/1002.json | 0 .../purchases/schemas/purchases-key.schema | 0 .../purchases/schemas/purchases-value.schema | 0 .../schemas/purchases_flat-key.schema | 0 .../schemas/purchases_flat-value.schema | 0 .../retail_store/replenishments/3000.json | 0 .../schemas/replenishments-key.schema | 0 .../schemas/replenishments-value.schema | 0 .../schemas/replenishments_flat-key.schema | 0 .../schemas/replenishments_flat-value.schema | 0 .../Resources/retail_store/returns/2000.json | 0 .../returns/schemas/returns-key.schema | 0 .../returns/schemas/returns-value.schema | 0 .../schemas/returns_flat-key.schema | 0 .../schemas/returns_flat-value.schema | 0 .../Student/Resources/terraform/DEPLOY.md | 0 .../Resources/terraform/api_key_check.sh | 0 .../Resources/terraform/generate_env_file.sh | 0 .../Student/Resources/terraform/main.tf | 0 .../Student/Resources/terraform/main_azure.tf | 0 .../Resources/terraform/main_confluent.tf | 0 .../Resources/terraform/main_outputs.tf | 0 .../Resources/terraform/terraform_cleanup.sh | 0 562 files changed, 148 insertions(+), 191 deletions(-) rename .devcontainer/{073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/devcontainer.json (93%) rename .github/{chatmodes => agents}/WTHAuthor.chatmode.md (100%) delete mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-00.md delete mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-01.md delete mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-02.md delete mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-03.md delete mode 100644 073-AIWithConfluentOnAzure/Coach/Solution-04.md rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Lectures.pptx (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/README.md (65%) create mode 100644 074-AIWithConfluentOnAzure/Coach/Solution-00.md create mode 100644 074-AIWithConfluentOnAzure/Coach/Solution-01.md create mode 100644 074-AIWithConfluentOnAzure/Coach/Solution-02.md create mode 100644 074-AIWithConfluentOnAzure/Coach/Solution-03.md create mode 100644 074-AIWithConfluentOnAzure/Coach/Solution-04.md rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/.gitkeep (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/README.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/data_pipeline-ddl.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/data_pipeline-dml.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/ddl-sink-tables.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/ddl-source-tables.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/departments.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/departments_flat.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/flat_tables.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/product_skus.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/purchases.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/replenishments.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/retail_tables.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/flink-sql/drafts/returns.sql (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/maintenance_scripts/check_resources_status.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/maintenance_scripts/environment-azure.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/maintenance_scripts/environment-confluent.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/README.md (68%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Challenge-00.md (61%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Challenge-01.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Challenge-02.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Challenge-03.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Challenge-04.md (89%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/.gitkeep (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/.dockerignore (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/.env.sh.example (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/DOCKER_BUILDS.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.base (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.customer (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.employee (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.inventory (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.replenishment (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.shopping (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/Dockerfile.supplier (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/LICENSE (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/NOTES.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/README.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/agent_customer_experience.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/agent_employee_experience.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/agent_supplier_experience.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/__init__.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/models.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/contoso_retail_application/utils.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/main.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/mcp_service.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/pyproject.toml (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/tests/test_replenishment.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/tests/test_sales.py (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/agentic-application/uv.lock (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/ai-search-schemas/departments_flat.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/ai-search-schemas/net_sales.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/ai-search-schemas/product_inventory.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/azure-setup-create-indices.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/compose/docker-compose.yml (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/compose/shared_environment_variables.env.example (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-cli.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-create-connectors.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-create-topics.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-delete-connectors.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-delete-schemas.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-delete-topics.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-flink-sql.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-populate-connector-configs.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/confluent-setup-populate-connector-reset.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/ai_search_departments_flat.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/ai_search_net_sales.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/ai_search_product_inventory.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/azure_blob_departments.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/azure_blob_product_skus.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/cosmos_db_purchases.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/connector-configurations/cosmos_db_returns.example.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/README.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/azure_blob_upload.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/appliance.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/cleaning.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/dairy.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/deli.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/meat.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/pharmacy.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/produce.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/schemas/departments-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/schemas/departments-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments/seafood.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/appliance.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/cleaning.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/dairy.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/deli.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/meat.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/pharmacy.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/produce.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/departments_flat/seafood.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/net_sales/101.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_inventory/101.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_inventory/102.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/101.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/102.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/103.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/104.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/105.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/106.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/107.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/108.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/109.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/110.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/111.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/112.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/113.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/114.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/115.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/116.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/117.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/118.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/119.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/120.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/121.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/122.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/123.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/124.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/125.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/201.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/202.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/203.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/204.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/205.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/206.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/207.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/208.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/209.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/210.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/211.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/212.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/213.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/214.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/215.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/216.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/217.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/218.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/219.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/220.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/221.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/222.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/223.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/224.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/225.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/301.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/302.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/303.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/304.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/305.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/306.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/307.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/308.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/309.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/310.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/311.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/312.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/313.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/314.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/315.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/316.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/317.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/318.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/319.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/320.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/321.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/322.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/323.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/324.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/325.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/401.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/402.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/403.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/404.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/405.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/406.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/407.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/408.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/409.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/410.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/411.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/412.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/413.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/414.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/415.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/416.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/417.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/418.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/419.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/420.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/421.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/422.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/423.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/424.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/425.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/501.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/502.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/503.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/504.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/505.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/506.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/507.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/508.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/509.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/510.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/511.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/512.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/513.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/514.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/515.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/516.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/517.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/518.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/519.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/520.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/521.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/522.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/523.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/524.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/525.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/601.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/602.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/603.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/604.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/605.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/606.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/607.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/608.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/609.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/610.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/611.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/612.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/613.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/614.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/615.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/616.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/617.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/618.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/619.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/620.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/621.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/622.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/623.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/624.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/625.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/701.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/702.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/703.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/704.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/705.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/706.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/707.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/708.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/709.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/710.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/711.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/712.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/713.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/714.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/715.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/716.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/717.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/718.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/719.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/720.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/721.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/722.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/723.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/724.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/725.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/801.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/802.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/803.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/804.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/805.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/806.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/807.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/808.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/809.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/810.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/811.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/812.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/813.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/814.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/815.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/816.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/817.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/818.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/819.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/820.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/821.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/822.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/823.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/824.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/825.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/101.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/102.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/103.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/104.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/105.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/106.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/107.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/108.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/109.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/110.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/111.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/112.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/113.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/114.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/115.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/116.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/117.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/118.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/119.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/120.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/121.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/122.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/123.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/124.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/125.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/201.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/202.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/203.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/204.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/205.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/206.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/207.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/208.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/209.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/210.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/211.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/212.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/213.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/214.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/215.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/216.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/217.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/218.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/219.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/220.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/221.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/222.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/223.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/224.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/225.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/301.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/302.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/303.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/304.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/305.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/306.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/307.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/308.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/309.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/310.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/311.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/312.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/313.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/314.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/315.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/316.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/317.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/318.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/319.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/320.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/321.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/322.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/323.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/324.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/325.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/401.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/402.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/403.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/404.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/405.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/406.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/407.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/408.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/409.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/410.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/411.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/412.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/413.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/414.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/415.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/416.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/417.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/418.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/419.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/420.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/421.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/422.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/423.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/424.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/425.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/501.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/502.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/503.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/504.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/505.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/506.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/507.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/508.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/509.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/510.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/511.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/512.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/513.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/514.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/515.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/516.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/517.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/518.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/519.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/520.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/521.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/522.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/523.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/524.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/525.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/601.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/602.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/603.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/604.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/605.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/606.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/607.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/608.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/609.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/610.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/611.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/612.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/613.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/614.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/615.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/616.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/617.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/618.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/619.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/620.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/621.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/622.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/623.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/624.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/625.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/701.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/702.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/703.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/704.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/705.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/706.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/707.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/708.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/709.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/710.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/711.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/712.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/713.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/714.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/715.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/716.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/717.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/718.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/719.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/720.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/721.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/722.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/723.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/724.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/725.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/801.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/802.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/803.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/804.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/805.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/806.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/807.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/808.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/809.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/810.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/811.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/812.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/813.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/814.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/815.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/816.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/817.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/818.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/819.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/820.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/821.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/822.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/823.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/824.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/825.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases/1000.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases/1001.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases/1002.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases/schemas/purchases-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases/schemas/purchases-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/replenishments/3000.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/returns/2000.json (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/returns/schemas/returns-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/returns/schemas/returns-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/DEPLOY.md (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/api_key_check.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/generate_env_file.sh (100%) mode change 100755 => 100644 rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/main.tf (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/main_azure.tf (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/main_confluent.tf (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/main_outputs.tf (100%) rename {073-AIWithConfluentOnAzure => 074-AIWithConfluentOnAzure}/Student/Resources/terraform/terraform_cleanup.sh (100%) mode change 100755 => 100644 diff --git a/.devcontainer/073-AIWithConfluentOnAzure/devcontainer.json b/.devcontainer/074-AIWithConfluentOnAzure/devcontainer.json similarity index 93% rename from .devcontainer/073-AIWithConfluentOnAzure/devcontainer.json rename to .devcontainer/074-AIWithConfluentOnAzure/devcontainer.json index 04ae874375..33b15f57ff 100644 --- a/.devcontainer/073-AIWithConfluentOnAzure/devcontainer.json +++ b/.devcontainer/074-AIWithConfluentOnAzure/devcontainer.json @@ -1,6 +1,6 @@ { "image": "mcr.microsoft.com/devcontainers/python:3.12-bookworm", - "workspaceFolder": "/workspace/073-AIWithConfluentOnAzure/Student/Resources", + "workspaceFolder": "/workspace/074-AIWithConfluentOnAzure/Student/Resources", "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached", "hostRequirements": { "cpus": 2, diff --git a/.github/chatmodes/WTHAuthor.chatmode.md b/.github/agents/WTHAuthor.chatmode.md similarity index 100% rename from .github/chatmodes/WTHAuthor.chatmode.md rename to .github/agents/WTHAuthor.chatmode.md diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-00.md b/073-AIWithConfluentOnAzure/Coach/Solution-00.md deleted file mode 100644 index 6ae2d64d2b..0000000000 --- a/073-AIWithConfluentOnAzure/Coach/Solution-00.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 00 - Prerequisites - Ready, Set, GO! - Coach's Guide - -**[Home](./README.md)** - [Next Solution >](./Solution-01.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-01.md b/073-AIWithConfluentOnAzure/Coach/Solution-01.md deleted file mode 100644 index 21709a8252..0000000000 --- a/073-AIWithConfluentOnAzure/Coach/Solution-01.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 01 - Build the Flink Data Pipeline - Coach's Guide - -[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-02.md b/073-AIWithConfluentOnAzure/Coach/Solution-02.md deleted file mode 100644 index be03319418..0000000000 --- a/073-AIWithConfluentOnAzure/Coach/Solution-02.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 02 - Supplier Experience - Coach's Guide - -[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-03.md b/073-AIWithConfluentOnAzure/Coach/Solution-03.md deleted file mode 100644 index 0f5569b237..0000000000 --- a/073-AIWithConfluentOnAzure/Coach/Solution-03.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 03 - Customer Experience - Coach's Guide - -[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Solution-04.md b/073-AIWithConfluentOnAzure/Coach/Solution-04.md deleted file mode 100644 index eb403c74fe..0000000000 --- a/073-AIWithConfluentOnAzure/Coach/Solution-04.md +++ /dev/null @@ -1,20 +0,0 @@ -# Challenge 04 - Employee Experience - Coach's Guide - -[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** - -## Notes & Guidance - -This is the only section you need to include. - -Use general non-bulleted text for the beginning of a solution area for this challenge - -- Then move into bullets - - And sub-bullets and even - - sub-sub-bullets - -Break things apart with more than one bullet list - -- Like this -- One -- Right -- Here diff --git a/073-AIWithConfluentOnAzure/Coach/Lectures.pptx b/074-AIWithConfluentOnAzure/Coach/Lectures.pptx similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Lectures.pptx rename to 074-AIWithConfluentOnAzure/Coach/Lectures.pptx diff --git a/073-AIWithConfluentOnAzure/Coach/README.md b/074-AIWithConfluentOnAzure/Coach/README.md similarity index 65% rename from 073-AIWithConfluentOnAzure/Coach/README.md rename to 074-AIWithConfluentOnAzure/Coach/README.md index 9b2a0d597e..cb8ba79faa 100644 --- a/073-AIWithConfluentOnAzure/Coach/README.md +++ b/074-AIWithConfluentOnAzure/Coach/README.md @@ -1,8 +1,8 @@ -# What The Hack - AIWithConfluentOnAzure - Coach Guide +# What The Hack - AI With Confluent On Azure - Coach Guide ## Introduction -Welcome to the coach's guide for the AIWithConfluentOnAzure What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. +Welcome to the coach's guide for the AI With Confluent On Azure What The Hack. Here you will find links to specific guidance for coaches for each of the challenges. This hack includes an optional [lecture presentation](Lectures.pptx) that features short presentations to introduce key topics associated with each challenge. It is recommended that the host present each short presentation before attendees kick off that challenge. @@ -35,43 +35,37 @@ Always refer students to the [What The Hack website](https://aka.ms/wth) for the **NOTE:** Students should **not** be given a link to the What The Hack repo before or during a hack. The student guide does **NOT** have any links to the Coach's guide or the What The Hack repo on GitHub. -### Additional Coach Prerequisites (Optional) +### Additional Coach Prerequisites -_Please list any additional pre-event setup steps a coach would be required to set up such as, creating or hosting a shared dataset, or deploying a lab environment._ +- Ensure you have a Confluent Cloud account with permissions to create Kafka clusters, topics, and connectors. +- Pre-provision or verify access to the required Azure services: Azure OpenAI, Azure Cosmos DB, Azure AI Search, Azure Redis Cache, and Azure Storage Account. +- Test the Terraform modules in the `Student/Resources/terraform` folder to ensure they deploy successfully in your target environment. ## Azure Requirements This hack requires students to have access to an Azure subscription where they can create and consume Azure resources. These Azure requirements should be shared with a stakeholder in the organization that will be providing the Azure subscription(s) that will be used by the students. -_Please list Azure subscription requirements._ +- Azure subscription with Owner access +- Ability to create the following resources: Azure OpenAI, Azure Cosmos DB, Azure AI Search, Azure Redis Cache, Azure Storage Account +- Sufficient quota for Azure OpenAI model deployments -_For example:_ +## Suggested Hack Agenda -- Azure resources that will be consumed by a student implementing the hack's challenges -- Azure permissions required by a student to complete the hack's challenges. - -## Suggested Hack Agenda (Optional) - -_This section is optional. You may wish to provide an estimate of how long each challenge should take for an average squad of students to complete and/or a proposal of how many challenges a coach should structure each session for a multi-session hack event. For example:_ - -- Sample Day 1 - - Challenge 1 (1 hour) - - Challenge 2 (30 mins) - - Challenge 3 (2 hours) -- Sample Day 2 - - Challenge 4 (45 mins) - - Challenge 5 (1 hour) - - Challenge 6 (45 mins) +- Challenge 00 (1 hour) - Prerequisites and infrastructure provisioning +- Challenge 01 (1.5 hours) - Build the Flink Data Pipeline +- Challenge 02 (1 hour) - Supplier Experience +- Challenge 03 (1 hour) - Customer Experience +- Challenge 04 (1 hour) - Employee Experience ## Repository Contents -_The default files & folders are listed below. You may add to this if you want to specify what is in additional sub-folders you may add._ - - `./Coach` - Coach's Guide and related files - `./Coach/Solutions` - Solution files with completed example answers to a challenge +- `./Coach/Lectures.pptx` + - Optional lecture presentations for each challenge - `./Student` - Student's Challenge Guide - `./Student/Resources` - - Resource files, sample code, scripts, etc meant to be provided to students. (Must be packaged up by the coach and provided to students at start of event) + - Terraform modules, configuration scripts, AI agent application code, and connector configurations meant to be provided to students (must be packaged up by the coach and provided to students at start of event) diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-00.md b/074-AIWithConfluentOnAzure/Coach/Solution-00.md new file mode 100644 index 0000000000..1f358e3ef5 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-00.md @@ -0,0 +1,18 @@ +# Challenge 00 - Prerequisites - Ready, Set, GO! - Coach's Guide + +**[Home](./README.md)** - [Next Solution >](./Solution-01.md) + +## Notes & Guidance + +Ensure students have all prerequisites installed before proceeding: + +- Verify students have Azure CLI, Terraform CLI, and Confluent CLI installed and authenticated +- Students should extract the Resources.zip file and navigate to the Terraform directory +- The Terraform modules require Azure subscription ID, principal IDs, and Confluent API keys to be set in the variables files +- Run `terraform init` followed by `terraform plan` and `terraform apply` to deploy all infrastructure +- Common issues: + - Insufficient Azure permissions or quota limits for Azure OpenAI + - Missing or incorrect Confluent Cloud API keys + - Terraform state lock issues if multiple students share a subscription +- After deployment, verify all connectors are in a "Running" state in Confluent Cloud +- Confirm the MCP-powered AI agent responds when prompted with its name and can list the eight grocery store departments diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-01.md b/074-AIWithConfluentOnAzure/Coach/Solution-01.md new file mode 100644 index 0000000000..19df90c6e3 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-01.md @@ -0,0 +1,21 @@ +# Challenge 01 - Build the Flink Data Pipeline - Coach's Guide + +[< Previous Solution](./Solution-00.md) - **[Home](./README.md)** - [Next Solution >](./Solution-02.md) + +## Notes & Guidance + +Students need to connect to the Apache Flink SQL editor in Confluent Cloud and create Flink tables mapped to existing Kafka topics. + +- Students must create Flink tables for all six topics: `product_sku`, `product_pricing`, `product_departments`, `purchases`, `returns`, and `replenishments` +- The merge logic for `net_sales` should: + - Add purchase amounts to the running total per SKU + - Subtract return amounts from the running total per SKU +- The merge logic for `net_inventory_count` should: + - Subtract purchase quantities from inventory per SKU + - Add replenishment quantities to inventory per SKU + - For returns: only add back to inventory if the product belongs to the appliance department; ignore returns from all other departments +- Reference Flink SQL solutions are available in the `Coach/Solutions/flink-sql` folder +- Common issues: + - Students may forget to handle the appliance department return logic + - Schema mismatches between Kafka topic schemas and Flink table definitions + - Flink SQL statements must be running continuously; verify they are active in the Confluent Cloud UI diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-02.md b/074-AIWithConfluentOnAzure/Coach/Solution-02.md new file mode 100644 index 0000000000..6ff9b4981c --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-02.md @@ -0,0 +1,14 @@ +# Challenge 02 - Supplier Experience - Coach's Guide + +[< Previous Solution](./Solution-01.md) - **[Home](./README.md)** - [Next Solution >](./Solution-03.md) + +## Notes & Guidance + +Students interact with the supplier agent to query and replenish inventory. + +- The supplier agent should display real-time inventory levels per SKU and per department +- When a student replenishes inventory, the change should be reflected in the `net_inventory_count` table and subsequently in Azure AI Search +- Verify students confirm that the AI agent retrieves updated values from MCP services after replenishment actions +- Common issues: + - Delays in data propagation from Kafka through Flink to Azure AI Search; allow a few seconds for updates + - If the agent returns stale data, check that the Flink SQL merge statements are running and the sink connector to Azure AI Search is active diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-03.md b/074-AIWithConfluentOnAzure/Coach/Solution-03.md new file mode 100644 index 0000000000..5813689152 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-03.md @@ -0,0 +1,15 @@ +# Challenge 03 - Customer Experience - Coach's Guide + +[< Previous Solution](./Solution-02.md) - **[Home](./README.md)** - [Next Solution >](./Solution-04.md) + +## Notes & Guidance + +Students simulate customer purchases and returns and observe real-time inventory and sales updates. + +- Students should record inventory levels before and after purchases/returns to validate the pipeline +- After a purchase, inventory should decrease and net sales should increase +- After a return, net sales should decrease; inventory should only increase if the returned product belongs to the appliance department +- The three-second update window is a guideline; slight delays are acceptable but data should converge quickly +- Common issues: + - Students may not observe updates if the sink connector to Azure AI Search has fallen behind + - Remind students to check both the `net_sales` and `net_inventory_count` values after each action diff --git a/074-AIWithConfluentOnAzure/Coach/Solution-04.md b/074-AIWithConfluentOnAzure/Coach/Solution-04.md new file mode 100644 index 0000000000..c1a11340c2 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Coach/Solution-04.md @@ -0,0 +1,16 @@ +# Challenge 04 - Employee Experience - Coach's Guide + +[< Previous Solution](./Solution-03.md) - **[Home](./README.md)** + +## Notes & Guidance + +Students use the employee agent to access comprehensive operational insights across all transactions. + +- This challenge requires students to use multiple personas simultaneously (customer, supplier, and employee) +- The employee agent should display inventory levels, cumulative purchase/return/replenishment units, and net sales for any SKU +- Students should trigger events from customer and supplier agents and then verify the employee agent reflects those changes +- All data shown by the employee agent should match what is observed in Azure AI Search and Flink output +- Common issues: + - Students may have difficulty managing multiple browser tabs or windows for different personas + - If cumulative values are incorrect, verify the Flink SQL merge logic from Challenge 01 is running correctly + - Ensure the sink connector is actively pushing updates to Azure AI Search diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep b/074-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep rename to 074-AIWithConfluentOnAzure/Coach/Solutions/.gitkeep diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-ddl.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/data_pipeline-dml.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-sink-tables.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/ddl-source-tables.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/departments_flat.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/flat_tables.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/product_skus.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/purchases.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/replenishments.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/retail_tables.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql rename to 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/drafts/returns.sql diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh rename to 074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh rename to 074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh rename to 074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-confluent.sh diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh rename to 074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh diff --git a/073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh rename to 074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_cosmos_db.sh diff --git a/073-AIWithConfluentOnAzure/README.md b/074-AIWithConfluentOnAzure/README.md similarity index 68% rename from 073-AIWithConfluentOnAzure/README.md rename to 074-AIWithConfluentOnAzure/README.md index 6c74e32238..4f32864eb2 100644 --- a/073-AIWithConfluentOnAzure/README.md +++ b/074-AIWithConfluentOnAzure/README.md @@ -2,9 +2,9 @@ ## Introduction -This hackathon immerses you in building a real-time AI agent using **Confluent Cloud on Microsoft Azure**. You’ll learn how Confluent’s data streaming platform—based on Apache Kafka—can connect and process retail data in real time, enabling AI-driven insights that keep pace with constantly changing business conditions [1][2]. Whether it’s ingesting product SKUs or synchronizing inventory levels, Confluent Cloud on Azure offers a unified, scalable, and secure platform to design near real-time pipelines and deliver accurate, intelligent solutions. +This hackathon immerses you in building a real-time AI agent using **Confluent Cloud on Microsoft Azure**. You’ll learn how Confluent’s data streaming platform—based on Apache Kafka—can connect and process retail data in real time, enabling AI-driven insights that keep pace with constantly changing business conditions. Whether it’s ingesting product SKUs or synchronizing inventory levels, Confluent Cloud on Azure offers a unified, scalable, and secure platform to design near real-time pipelines and deliver accurate, intelligent solutions. -Throughout this hack, you’ll capture data from diverse sources—such as transaction logs, returns, and purchase records—and then transform or enrich that data using Apache Flink or ksqlDB. The result is an always up-to-date data backbone, ready to power AI-driven applications that swiftly respond to customer needs, supplier demands, and dynamic inventory scenarios [3][4]. +Throughout this hack, you’ll capture data from diverse sources—such as transaction logs, returns, and purchase records—and then transform or enrich that data using Apache Flink or ksqlDB. The result is an always up-to-date data backbone, ready to power AI-driven applications that swiftly respond to customer needs, supplier demands, and dynamic inventory scenarios. ## Learning Objectives @@ -36,11 +36,22 @@ By completing this hack, you will: - Visual Studio Code - Azure CLI -## References -- 1 https://www.confluent.io/apache-kafka-vs-confluent/ -- 2 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/overview -- 3 https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create -- 4 https://www.confluent.io/hub/ +## Learning Resources +- [Apache Kafka vs Confluent](https://www.confluent.io/apache-kafka-vs-confluent/) +- [What is Apache Kafka & Confluent Cloud on Azure?](https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/overview) +- [Create an Apache Kafka & Confluent Cloud resource](https://learn.microsoft.com/en-us/azure/partner-solutions/apache-kafka-confluent-cloud/create) +- [Confluent Hub](https://www.confluent.io/hub/) + +## Repository Contents + +- `./Coach` + - Coach's Guide and related files +- `./Coach/Solutions` + - Solution files with completed example answers to a challenge +- `./Student` + - Student's Challenge Guide +- `./Student/Resources` + - Terraform modules, configuration scripts, AI agent application code, and connector configurations (packaged by coach as Resources.zip) ## Contributors diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-00.md b/074-AIWithConfluentOnAzure/Student/Challenge-00.md similarity index 61% rename from 073-AIWithConfluentOnAzure/Student/Challenge-00.md rename to 074-AIWithConfluentOnAzure/Student/Challenge-00.md index 030a94ca45..1044859552 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-00.md +++ b/074-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -14,57 +14,27 @@ By the end of this challenge, you should have: ## Common Prerequisites -We have compiled a list of common tools and software that you will need to complete Challenge 1 and deploy the Terraform-based infrastructure to Azure and Confluent Cloud. +We have compiled a list of common tools and software that you will need to complete this hack and deploy the Terraform-based infrastructure to Azure and Confluent Cloud. You may not need all of them outside this challenge. However, if you work with Azure or Confluent Cloud on a regular basis, these are essential components for your development toolkit. -* **Azure Subscription** +- [Azure Subscription](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-subscription) +- [Managing Cloud Resources](../../000-HowToHack/WTH-Common-Prerequisites.md#managing-cloud-resources) + - [Azure Portal](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-portal) + - [Azure CLI](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-cli) + - [Note for Windows Users](../../000-HowToHack/WTH-Common-Prerequisites.md#note-for-windows-users) +- [Visual Studio Code](../../000-HowToHack/WTH-Common-Prerequisites.md#visual-studio-code) +- [Azure Storage Explorer](../../000-HowToHack/WTH-Common-Prerequisites.md#azure-storage-explorer) - * You must have access to an active Azure subscription with permissions to create resources. -* **Managing Cloud Resources** +In addition to the common prerequisites above, you will need the following tools specific to this hack: - * **Azure Portal** - [https://portal.azure.com](https://portal.azure.com) - Used to visually validate resources deployed by Terraform. - * **Azure CLI** - [https://learn.microsoft.com/cli/azure/install-azure-cli](https://learn.microsoft.com/cli/azure/install-azure-cli) - Required to authenticate and verify your subscription and resource group. +* **[Terraform CLI](https://developer.hashicorp.com/terraform/downloads)** + - Required to deploy infrastructure modules for Azure and Confluent Cloud + - After installation, verify by running: `terraform init` - * After installation, login using: - - ```bash - az login - ``` - * **Terraform CLI** - [https://developer.hashicorp.com/terraform/downloads](https://developer.hashicorp.com/terraform/downloads) - Required to deploy infrastructure modules for Azure and Confluent Cloud. - - * After installation, you should be able to run the following command with the Terraform CLI: - ```bash - terraform init - ``` -* **Confluent Cloud CLI** - - * Required to authenticate to Confluent Cloud and interact with Kafka topics and connectors - [https://docs.confluent.io/confluent-cli/current/install.html](https://docs.confluent.io/confluent-cli/current/install.html) - - Use the following command to authenticate with Confluent Cloud via the CLI: - ```bash - confluent --help - - ``` - -Optional but helpful: - -* **Visual Studio Code** - - * Recommended IDE for editing Terraform configuration files - [https://code.visualstudio.com](https://code.visualstudio.com) - -* **Azure Storage Explorer** - - * Helpful for inspecting Blob Storage input files during validation - [https://azure.microsoft.com/features/storage-explorer/](https://azure.microsoft.com/features/storage-explorer/) +* **[Confluent Cloud CLI](https://docs.confluent.io/confluent-cli/current/install.html)** + - Required to authenticate to Confluent Cloud and interact with Kafka topics and connectors + - After installation, verify by running: `confluent --help` ## Description @@ -101,30 +71,30 @@ To complete this challenge successfully, you should be able to: ## Learning Resources -* **Install Azure CLI** - [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) +* **Install Azure CLI:** + [Azure CLI Installation Guide](https://learn.microsoft.com/cli/azure/install-azure-cli) -* **Install Terraform CLI** - [Terraform CLI](https://developer.hashicorp.com/terraform/downloads) +* **Install Terraform CLI:** + [Terraform CLI Downloads](https://developer.hashicorp.com/terraform/downloads) -* **Install Confluent CLI** - [Confluent CLI](https://docs.confluent.io/confluent-cli/current/install.html) +* **Install Confluent CLI:** + [Confluent CLI Installation Guide](https://docs.confluent.io/confluent-cli/current/install.html) -* **Azure Service Principal authentication** +* **Azure Service Principal authentication:** [Azure Service Principal Setup](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal) -* **Confluent Cloud getting started** +* **Confluent Cloud getting started:** [Confluent Cloud on Azure](https://docs.confluent.io/cloud/current/get-started/index.html) -* **Confluent Connector Hub** +* **Confluent Connector Hub:** [Azure Connectors for Confluent](https://www.confluent.io/hub/plugins?query=azure) -* **Confluent Source & Sink Connectors** +* **Confluent Source & Sink Connectors:** [Kafka Connectors from Confluent](https://docs.confluent.io/cloud/current/connectors/index.html) -* **Azure AI Search documentation** +* **Azure AI Search documentation:** [Azure AI Search Docs](https://learn.microsoft.com/azure/search/search-what-is-azure-search) -* **Azure Cosmos DB documentation** +* **Azure Cosmos DB documentation:** [Azure Cosmos DB Docs](https://learn.microsoft.com/azure/cosmos-db/introduction) diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-01.md b/074-AIWithConfluentOnAzure/Student/Challenge-01.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Challenge-01.md rename to 074-AIWithConfluentOnAzure/Student/Challenge-01.md diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-02.md b/074-AIWithConfluentOnAzure/Student/Challenge-02.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Challenge-02.md rename to 074-AIWithConfluentOnAzure/Student/Challenge-02.md diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-03.md b/074-AIWithConfluentOnAzure/Student/Challenge-03.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Challenge-03.md rename to 074-AIWithConfluentOnAzure/Student/Challenge-03.md diff --git a/073-AIWithConfluentOnAzure/Student/Challenge-04.md b/074-AIWithConfluentOnAzure/Student/Challenge-04.md similarity index 89% rename from 073-AIWithConfluentOnAzure/Student/Challenge-04.md rename to 074-AIWithConfluentOnAzure/Student/Challenge-04.md index 86f1f56d00..1284ccde5d 100644 --- a/073-AIWithConfluentOnAzure/Student/Challenge-04.md +++ b/074-AIWithConfluentOnAzure/Student/Challenge-04.md @@ -26,8 +26,6 @@ During this challenge, you will: - Confirm that the employee agent responds with accurate net inventory counts and net sales values - Verify that all data matches what is observed in Azure AI Search and Flink output -This challenge requires interaction across multiple personas. You will switch between customer, supplier, and employee tabs or windows to simulate real-world concurrent activity. Each action triggers updates to the net inventory count and net sales tables, and the employee agent should always return accurate, real-time data. - ## Success Criteria To complete this challenge successfully, you should be able to: diff --git a/073-AIWithConfluentOnAzure/Student/Resources/.gitkeep b/074-AIWithConfluentOnAzure/Student/Resources/.gitkeep similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/.gitkeep rename to 074-AIWithConfluentOnAzure/Student/Resources/.gitkeep diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.dockerignore diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/.env.sh.example diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/DOCKER_BUILDS.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.base diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.customer diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.employee diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.inventory diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.replenishment diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.shopping diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/Dockerfile.supplier diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/LICENSE diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/NOTES.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/README.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_customer_experience.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_employee_experience.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/agent_supplier_experience.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/__init__.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/agent_graphs.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/ai_foundry_setup.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/data_access_objects.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/models.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_inventory.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_replenishment.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/service_configuration_shopping.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/static_dataset.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/contoso_retail_application/utils.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-customer.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-employee.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.agent-supplier.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-inventory.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-replenishment.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/entrypoints/entrypoint.mcp-shopping.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/main.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/mcp_service.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/pyproject.toml diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_replenishment.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/tests/test_sales.py diff --git a/073-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock rename to 074-AIWithConfluentOnAzure/Student/Resources/agentic-application/uv.lock diff --git a/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json rename to 074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/departments_flat.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json rename to 074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/net_sales.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json b/074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json rename to 074-AIWithConfluentOnAzure/Student/Resources/ai-search-schemas/product_inventory.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh b/074-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/azure-setup-create-indices.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml b/074-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml rename to 074-AIWithConfluentOnAzure/Student/Resources/compose/docker-compose.yml diff --git a/073-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example b/074-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example rename to 074-AIWithConfluentOnAzure/Student/Resources/compose/shared_environment_variables.env.example diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-cli.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-flink-sql.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_departments_flat.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_net_sales.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/ai_search_product_inventory.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_purchases.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_replenishments.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json rename to 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_returns.example.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/schemas/departments-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/appliance.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/cleaning.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/dairy.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/deli.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/meat.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/pharmacy.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/produce.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/schemas/departments_flat-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments_flat/seafood.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/101.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/net_sales/schemas/net_sales-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/101.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/102.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_inventory/schemas/product_inventory-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/101.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/102.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/103.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/104.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/105.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/106.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/107.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/108.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/109.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/110.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/111.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/112.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/113.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/114.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/115.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/116.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/117.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/118.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/119.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/120.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/121.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/122.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/123.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/124.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/125.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/201.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/202.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/203.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/204.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/205.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/206.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/207.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/208.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/209.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/210.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/211.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/212.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/213.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/214.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/215.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/216.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/217.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/218.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/219.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/220.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/221.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/222.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/223.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/224.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/225.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/301.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/302.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/303.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/304.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/305.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/306.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/307.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/308.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/309.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/310.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/311.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/312.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/313.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/314.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/315.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/316.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/317.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/318.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/319.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/320.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/321.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/322.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/323.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/324.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/325.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/401.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/402.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/403.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/404.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/405.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/406.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/407.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/408.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/409.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/410.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/411.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/412.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/413.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/414.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/415.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/416.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/417.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/418.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/419.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/420.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/421.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/422.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/423.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/424.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/425.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/501.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/502.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/503.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/504.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/505.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/506.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/507.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/508.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/509.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/510.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/511.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/512.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/513.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/514.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/515.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/516.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/517.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/518.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/519.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/520.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/521.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/522.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/523.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/524.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/525.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/601.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/602.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/603.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/604.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/605.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/606.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/607.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/608.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/609.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/610.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/611.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/612.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/613.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/614.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/615.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/616.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/617.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/618.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/619.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/620.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/621.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/622.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/623.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/624.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/625.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/701.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/702.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/703.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/704.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/705.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/706.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/707.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/708.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/709.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/710.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/711.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/712.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/713.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/714.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/715.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/716.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/717.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/718.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/719.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/720.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/721.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/722.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/723.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/724.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/725.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/801.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/802.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/803.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/804.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/805.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/806.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/807.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/808.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/809.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/810.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/811.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/812.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/813.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/814.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/815.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/816.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/817.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/818.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/819.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/820.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/821.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/822.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/823.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/824.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/825.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_pricing/schemas/product_pricing-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/101.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/102.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/103.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/104.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/105.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/106.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/107.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/108.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/109.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/110.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/111.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/112.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/113.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/114.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/115.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/116.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/117.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/118.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/119.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/120.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/121.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/122.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/123.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/124.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/125.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/201.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/202.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/203.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/204.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/205.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/206.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/207.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/208.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/209.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/210.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/211.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/212.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/213.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/214.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/215.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/216.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/217.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/218.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/219.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/220.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/221.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/222.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/223.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/224.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/225.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/301.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/302.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/303.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/304.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/305.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/306.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/307.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/308.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/309.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/310.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/311.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/312.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/313.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/314.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/315.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/316.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/317.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/318.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/319.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/320.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/321.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/322.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/323.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/324.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/325.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/401.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/402.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/403.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/404.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/405.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/406.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/407.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/408.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/409.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/410.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/411.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/412.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/413.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/414.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/415.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/416.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/417.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/418.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/419.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/420.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/421.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/422.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/423.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/424.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/425.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/501.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/502.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/503.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/504.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/505.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/506.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/507.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/508.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/509.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/510.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/511.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/512.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/513.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/514.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/515.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/516.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/517.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/518.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/519.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/520.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/521.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/522.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/523.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/524.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/525.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/601.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/602.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/603.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/604.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/605.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/606.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/607.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/608.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/609.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/610.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/611.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/612.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/613.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/614.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/615.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/616.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/617.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/618.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/619.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/620.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/621.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/622.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/623.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/624.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/625.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/701.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/702.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/703.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/704.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/705.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/706.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/707.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/708.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/709.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/710.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/711.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/712.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/713.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/714.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/715.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/716.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/717.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/718.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/719.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/720.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/721.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/722.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/723.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/724.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/725.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/801.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/802.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/803.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/804.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/805.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/806.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/807.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/808.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/809.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/810.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/811.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/812.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/813.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/814.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/815.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/816.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/817.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/818.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/819.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/820.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/821.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/822.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/823.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/824.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/825.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/product_skus/schemas/product_skus-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1000.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1001.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/1002.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases/schemas/purchases-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/purchases_flat/schemas/purchases_flat-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/3000.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments/schemas/replenishments-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/replenishments_flat/schemas/replenishments_flat-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/2000.json diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns/schemas/returns-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-key.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema rename to 074-AIWithConfluentOnAzure/Student/Resources/retail_store/returns_flat/schemas/returns_flat-value.schema diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md b/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/api_key_check.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf diff --git a/073-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh old mode 100755 new mode 100644 similarity index 100% rename from 073-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh rename to 074-AIWithConfluentOnAzure/Student/Resources/terraform/terraform_cleanup.sh From f4458779e790969b48a0936bac5e6e3afb7808ac Mon Sep 17 00:00:00 2001 From: "Peter C. Laudati" <plaudati@hotmail.com> Date: Tue, 10 Mar 2026 13:08:00 -0400 Subject: [PATCH 25/32] Add wordlist for AI with Confluent on Azure --- 074-AIWithConfluentOnAzure/.wordlist.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 074-AIWithConfluentOnAzure/.wordlist.txt diff --git a/074-AIWithConfluentOnAzure/.wordlist.txt b/074-AIWithConfluentOnAzure/.wordlist.txt new file mode 100644 index 0000000000..ddef6fc810 --- /dev/null +++ b/074-AIWithConfluentOnAzure/.wordlist.txt @@ -0,0 +1,5 @@ +Flink +DDL +DML +Confluent +Confluent's From 7406856eecee4925196bd909ac1aeb58a6d75c74 Mon Sep 17 00:00:00 2001 From: "Peter C. Laudati" <plaudati@hotmail.com> Date: Tue, 10 Mar 2026 13:29:19 -0400 Subject: [PATCH 26/32] Add ksqlDB to the wordlist --- 074-AIWithConfluentOnAzure/.wordlist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/074-AIWithConfluentOnAzure/.wordlist.txt b/074-AIWithConfluentOnAzure/.wordlist.txt index ddef6fc810..b6f0d0c419 100644 --- a/074-AIWithConfluentOnAzure/.wordlist.txt +++ b/074-AIWithConfluentOnAzure/.wordlist.txt @@ -3,3 +3,4 @@ DDL DML Confluent Confluent's +ksqlDB From 87148d5654fcb0987aad927177cef44b3cf6449c Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Mon, 16 Mar 2026 21:33:58 -0700 Subject: [PATCH 27/32] Delete .github/agents/WTHAuthor.chatmode.md Moving to its own PR --- .github/agents/WTHAuthor.chatmode.md | 316 --------------------------- 1 file changed, 316 deletions(-) delete mode 100644 .github/agents/WTHAuthor.chatmode.md diff --git a/.github/agents/WTHAuthor.chatmode.md b/.github/agents/WTHAuthor.chatmode.md deleted file mode 100644 index 664255cb7b..0000000000 --- a/.github/agents/WTHAuthor.chatmode.md +++ /dev/null @@ -1,316 +0,0 @@ ---- -description: 'What The Hack content authoring assistant - helps create challenge-based hackathon content following WTH guidelines' ---- - -# What The Hack Content Authoring Assistant - -You are a specialized assistant for authoring What The Hack (WTH) content. What The Hack is a challenge-based hackathon format where participants learn through hands-on problem-solving rather than step-by-step instructions. - -**IMPORTANT INSTRUCTIONS:** -1. When reviewing or fixing WTH content, IMPLEMENT the changes directly using file editing tools rather than just suggesting them. Only explain what you're doing without asking for permission first. -2. ALWAYS review ALL WTH guidelines and requirements listed below BEFORE completing any task. Ensure every requirement is met - do not skip or forget any guideline. -3. You are EMPOWERED to restructure content to match WTH templates: - - Remove sections that don't belong in the template - - Rename sections to match template naming conventions - - Reorder sections to match the required template structure - - Add missing required sections -4. After making changes, verify that ALL WTH compliance rules have been followed, especially: - - No ordered/numbered lists in challenge descriptions (EXCEPT Challenge 00 - Prerequisites) - - No links from student content to coach solutions or WTH repo - - Success criteria use action verbs (Verify, Validate, Demonstrate, Show) - - All links have descriptive text (no bare URLs) - - Section names and structure match the official templates - - Correct spelling and capitalization of all Azure services and technology names (e.g., "Azure Kubernetes Service" not "azure kubernetes service", "Cosmos DB" not "CosmosDB") - -## Core Principles - -- **Challenge-Based Learning**: WTH is about making attendees learn by solving problems, NOT blindly following step-by-step instructions -- **Share After Event**: Content can be shared with attendees ONLY after the event is over -- **Coach Separation**: Student content must never link to Coach solutions or the WTH GitHub repo - -## Required Hack Structure - -Every What The Hack consists of: - -### 1. Hack Description (README.md in hack root) -**Must include:** -- **Hack Title**: Short but fun name, more than just technology names -- **Introduction**: Sell the hack - what technologies, why they matter, real-world scenarios (1-2 paragraphs) -- **Learning Objectives**: Short list of key learnings/outcomes -- **Challenges**: List of challenges with one-sentence descriptions, linked to individual challenge pages -- **Prerequisites(Optional)**: - - Assumed knowledge (e.g., "basic understanding of containers") - - Required tools/software - - Link to WTH Common Prerequisites if applicable -- **Repository Contents** (Optional): Catalog of provided files -- **Contributors**: Names and optional contact info of authors - -### 2. Challenge Files (Student/ChallengeXX.md) - -**Structure:** -- Navigation links (previous/home/next) using relative paths -- **Pre-requisites** (Optional): If specific previous challenges required -- **Introduction**: Overview of technologies/tasks, technical context, new lessons -- **Description**: Clear goals and high-level instructions (2-3 paragraphs max) - - Use bullet lists, NOT ordered lists (no step-by-step!) - - **EXCEPTION**: Challenge 00 (Prerequisites) MAY use ordered/numbered lists and step-by-step instructions since it's focused on setup, not core learning objectives - - May use sub-headers to organize sections - - Reference resources from Resources.zip provided by coach (OR Codespaces if the hack includes a devcontainer) - - NO direct links to WTH repo (exception: raw links to PDFs/Office docs) -- **Success Criteria**: Verifiable checks (start with "Validate...", "Verify...", "Show...", "Demonstrate...") -- **Learning Resources**: Relevant links with descriptive text (not just URLs) -- **Tips** (Optional): Hints and food for thought -- **Advanced Challenges** (Optional): Extra goals for eager participants - -**Key Rules:** -- NO step-by-step instructions (except Challenge 00) -- Multiple solution paths are OK -- Provide verifiable success criteria -- Include relevant learning resources -- Hint at time-consuming low-value items - -### 3. Challenge Design Principles - -**Include Challenge 0**: Helps attendees install all prerequisites -- Challenge 00 is the ONLY challenge where step-by-step instructions and ordered lists are permitted -- May provide detailed setup instructions for tools, environments, and dependencies - -**Cumulative Challenges:** -- Start small and simple ("Hello World") -- Build progressively more complex but allow for modularity for students to cherry pick content -- Establish confidence → Build competence -- Each challenge has educational value (even if only 3 of 7 completed) - - -### 4. Student Resources (Student/Resources/) - -- Provide code, templates, samples, or artifacts for challenges -- ideally a codespace to allow for most pre-req to be installed - -### 5. Coach's Guide (Coach/README.md) - -**The "owner's manual" for future coaches, including:** -- High-level solution steps to each challenge -- Known blockers and recommended hints -- Key concepts to explain before each challenge -- Reference links/articles/documentation for when students stuck -- Estimated time per challenge (NOT for students) - -### 6. Coach Solutions (Coach/Solutions/) - -- Example solutions (one way to solve challenges) -- Full working applications, configs, templates -- Prerequisites for Azure environment if needed -- Scripts/templates to share if teams really stuck -- NOT intended for attendees before/during event (but publicly available) - -## Directory Structure - -``` -XXX-YourHackName/ -├── README.md (Hack Description) -├── Coach/ -│ ├── README.md (Coach's Guide) -│ ├── Solution-01.md -│ ├── Solution-02.md -│ ├── ... -│ ├── Lectures.pptx (Optional) -│ └── Solutions/ -│ ├── (example code) -│ ├── (templates) -│ └── (configs) -└── Student/ - ├── Challenge-00.md - ├── Challenge-01.md - ├── Challenge-02.md - ├── ... - └── Resources/ - ├── (sample code) - ├── (templates) - └── (artifacts) -``` - -## Content Guidelines - -### What to DO: -- ✅ Use bullet lists for goals and specifications -- ✅ Use relative links for navigation (./ChallengeXX.md) -- ✅ Use descriptive link text (not bare URLs) -- ✅ Refer to Resources.zip in student challenges -- ✅ Keep challenge descriptions concise (shorter than the authoring guide!) -- ✅ Provide verifiable success criteria -- ✅ Include relevant learning resources -- ✅ Allow multiple solution paths -- ✅ Hint at time-consuming low-value items - -### What NOT to DO: -- ❌ NO step-by-step instructions in student challenges -- ❌ NO ordered/numbered lists in challenge descriptions (indicates step-by-step) -- ❌ NO links from student guide to WTH repo or Coach solutions -- ❌ NO absolute links to WTH repo (use relative links) -- ❌ NO bare URLs (use descriptive link text) -- ❌ NO sharing success criteria time estimates with students -- ❌ NO making challenges too verbose - -## Templates Available - -All templates are in `000-HowToHack/`: -- `WTH-HackDescription-Template.md` → Hack README.md -- `WTH-Challenge-Template.md` → Student/ChallengeXX.md -- `WTH-CoachGuide-Template.md` → Coach/README.md -- `WTH-Challenge-Solution-Template.md` → Coach/Solution-XX.md -- `WTH-ChallengeZero-Template.md` → Student/Challenge-00.md - -## Your Role as Authoring Assistant - -When helping authors: - -1. **Structure Guidance**: Help create proper directory structure and file organization -2. **Content Review**: Check that content follows WTH guidelines -3. **Template Usage**: Guide authors to use appropriate templates -4. **Challenge Design**: Ensure challenges are educational, progressive, and verifiable -5. **Link Validation**: Verify no student-to-coach or repo links -6. **Tone Check**: Ensure concise, challenge-based (not step-by-step) language -7. **Success Criteria**: Help write verifiable success criteria -8. **Resource Organization**: Guide proper placement of student vs coach resources - -Always remind authors that: -- Challenges should make attendees LEARN by solving problems -- Content will be publicly available (attendees can find it if determined) -- Coach's Guide can be written post-event based on first run learnings -- Quality content takes time but the format makes it easier to maintain - -## Quick Reference Checklist - -When reviewing/creating WTH content: - -**Hack Description (README.md):** -- [ ] Has engaging title and introduction -- [ ] Lists clear learning objectives -- [ ] Lists all challenges with descriptions -- [ ] Specifies prerequisites (knowledge + tools) -- [ ] Credits all contributors - -**Student Challenges:** -- [ ] Has navigation links (relative paths) -- [ ] Introduction provides context -- [ ] Description is concise (not step-by-step) -- [ ] Uses bullet lists (not ordered lists) -- [ ] Has verifiable success criteria -- [ ] Includes learning resources with descriptive links -- [ ] NO links to WTH repo or Coach solutions -- [ ] Correct spelling and capitalization of Azure/tech service names - -**Coach's Guide:** -- [ ] Has navigation links (relative paths) -- [ ] High-level solution steps -- [ ] Known blockers and hints -- [ ] Time estimates per challenge -- [ ] Key concepts to explain -- [ ] Reference materials - -**Coach Solutions:** -- [ ] Example working solutions -- [ ] Templates/scripts to share if stuck -- [ ] Pre-req setup instructions - -**Structure:** -- [ ] Proper directory layout (Coach/, Student/, Student/Resources/) -- [ ] Challenge numbering starts at 00 -- [ ] All navigation links work -- [ ] Resources properly packaged - -## Azure & Technology Service Name Standards - -When reviewing content, verify correct spelling and capitalization of service names: - -**Common Azure Services:** -- Azure Kubernetes Service (AKS) - not "Azure Kubernetes Services" -- Azure Container Instances (ACI) -- Azure Cosmos DB - not "CosmosDB" or "Cosmos Db" -- Azure OpenAI - not "Azure Open AI" -- Azure AI Search - not "Azure Search" or "Azure Cognitive Search" (legacy name) -- Azure Functions - not "Azure Function" -- Azure App Service - not "App Services" -- Azure Storage Account -- Azure Virtual Machines (VMs) -- Azure SQL Database - not "Azure SQL DB" -- Azure Key Vault - not "Key vault" or "KeyVault" -- Azure Monitor -- Azure DevOps -- Azure Active Directory (Azure AD) or Microsoft Entra ID (newer name) -- Azure Container Registry (ACR) - -**Other Technologies:** -- Terraform - not "terraform" -- Kubernetes - not "kubernetes" or "K8s" in formal documentation -- Docker - not "docker" -- GitHub - not "Github" -- Visual Studio Code (VS Code) - -## Common Violations to Flag - -### ❌ BAD: Ordered Lists (Step-by-Step) -```markdown -1. First, create a resource group -2. Next, deploy the ARM template -3. Finally, verify the deployment -``` - -### ✅ GOOD: Bullet Lists (Challenge-Based) -```markdown -- Create a resource group for your resources -- Deploy infrastructure using Infrastructure as Code -- Verify all resources are running correctly -``` - ---- - -### ❌ BAD: Links to Coach/Repo -```markdown -[Solution](../../Coach/Solution-01.md) -[Code](https://github.com/Microsoft/WhatTheHack/...) -``` - -### ✅ GOOD: Reference Resources.zip -```markdown -Refer to the starter code in the Resources.zip file provided by your coach. -``` - ---- - -### ❌ BAD: Vague Success Criteria -```markdown -- Understand how containers work -- Learn about Kubernetes -``` - -### ✅ GOOD: Verifiable Success Criteria -```markdown -- Verify your container is running using `docker ps` -- Demonstrate that your pod is in Running state -- Show that your application responds to HTTP requests -``` - ---- - -### ❌ BAD: Bare URLs -```markdown -https://docs.microsoft.com/azure/... -``` - -### ✅ GOOD: Descriptive Links -```markdown -[Azure Container Instances Documentation](https://docs.microsoft.com/azure/...) -``` - -## Response Style - -When helping with WTH content: -- Point out violations of WTH guidelines clearly -- Suggest rewording step-by-step text as challenge-based goals -- Flag any student→coach or student→repo links immediately -- Recommend using templates for new content -- Validate structure matches required format -- Check that success criteria are verifiable -- Ensure learning resources are relevant and descriptive \ No newline at end of file From 19c1481508662a280a00115a20a0ad7b7fc7d5e9 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:12:42 -0700 Subject: [PATCH 28/32] Add 'replenishments' and 'upsert' to wordlist --- 074-AIWithConfluentOnAzure/.wordlist.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/074-AIWithConfluentOnAzure/.wordlist.txt b/074-AIWithConfluentOnAzure/.wordlist.txt index b6f0d0c419..80ddf9d42b 100644 --- a/074-AIWithConfluentOnAzure/.wordlist.txt +++ b/074-AIWithConfluentOnAzure/.wordlist.txt @@ -4,3 +4,5 @@ DML Confluent Confluent's ksqlDB +replenishments +upsert From 43e5bfc299fffa93a018065524ab12df0c0312dc Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:13:21 -0700 Subject: [PATCH 29/32] Fix typo in replenishments description --- .../Student/Resources/retail_store/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md index a13df67658..b072f5f510 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/README.md @@ -6,6 +6,6 @@ We have data for the following collections: - product_pricing - the unit price for each sku - purchases - transactions where customers purchased one or more items - returns - transactions where customers returned one or more items -- replenishments - transactions where suppliers replinished one or more items +- replenishments - transactions where suppliers replenish one or more items - product_inventory - the global inventory count for each SKU -- net_sales - the global view sales for a particular SKU considering returns as well \ No newline at end of file +- net_sales - the global view sales for a particular SKU considering returns as well From 79877e62c3cd3accc15b74d7fcfa4cd3e9b81f77 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:14:03 -0700 Subject: [PATCH 30/32] Fix typo in RUNNING_THE_APPLICATION.md --- .../Resources/agentic-application/RUNNING_THE_APPLICATION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md index d295efbb3a..3add4b2941 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md +++ b/074-AIWithConfluentOnAzure/Student/Resources/agentic-application/RUNNING_THE_APPLICATION.md @@ -10,7 +10,7 @@ uv venv ## Activating the Virtual Environment -You can run these commands to activiate the virtual environment +You can run these commands to activate the virtual environment ### On Mac OS X or Linux @@ -139,4 +139,4 @@ uv run agent_supplier_experience.py # this is for the customer experience to search SKUs, make purchases, return previous purchases uv run agent_customer_experience.py -``` \ No newline at end of file +``` From d44e26489aff34c9b56660eeb087fc7ec68f14c5 Mon Sep 17 00:00:00 2001 From: Andy Huang <54148527+Whowong@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:17:52 -0700 Subject: [PATCH 31/32] Fix typo in README.md regarding data stores --- 074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md index 04e22a4519..513b52ab13 100644 --- a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md @@ -2,7 +2,7 @@ ## Data Pipeline Overview The goal of the pipeline is to ensure that -- the data from the source datastores (Cosmos and Blob store) flows into Kafka topics +- the data from the source data stores (Cosmos and Blob store) flows into Kafka topics - the data from the topics are joined and merged into transient tables - the data from the transient tables to finalized into the summary topics and tables - the data from the summary tables and pushed out to Azure AI search for the AI agent to use via MCP From 248022e8cb3a476ae423b5d84bbd9034bc60b01c Mon Sep 17 00:00:00 2001 From: Israel Ekpo <isekpo@microsoft.com> Date: Thu, 19 Mar 2026 00:05:03 -0400 Subject: [PATCH 32/32] Saving changes from Github Copilot edits --- .../Coach/Solutions/flink-sql/README.md | 2 +- .../check_resources_status.sh | 28 -------- .../maintenance_scripts/environment-azure.sh | 2 - .../fix_azure_blob_store.sh | 12 ---- .../Student/Challenge-00.md | 6 +- .../confluent-setup-create-connectors.sh | 11 ++- .../confluent-setup-create-topics.sh | 2 +- .../confluent-setup-delete-connectors.sh | 4 +- .../confluent-setup-delete-schemas.sh | 2 +- .../confluent-setup-delete-topics.sh | 2 +- ...fluent-setup-populate-connector-configs.sh | 6 +- ...onfluent-setup-populate-connector-reset.sh | 6 +- .../azure_blob_departments.example.json | 35 ---------- .../azure_blob_product_pricing.example.json | 35 ---------- .../azure_blob_product_skus.example.json | 35 ---------- .../cosmos_db_departments.example.json | 27 ++++++++ .../cosmos_db_product_pricing.example.json | 27 ++++++++ .../cosmos_db_product_skus.example.json | 27 ++++++++ .../UPLOADING_BLOB_STORE_CONTENTS.md | 19 ------ .../UPLOADING_COSMOS_DB_CONTENTS.md | 23 +++++++ .../retail_store/azure_blob_upload.sh | 38 ----------- .../retail_store/azure_cosmos_upload.sh | 50 ++++++++++++++ .../retail_store/departments/appliance.json | 1 + .../retail_store/departments/cleaning.json | 1 + .../retail_store/departments/dairy.json | 1 + .../retail_store/departments/deli.json | 1 + .../retail_store/departments/meat.json | 1 + .../retail_store/departments/pharmacy.json | 1 + .../retail_store/departments/produce.json | 1 + .../retail_store/departments/seafood.json | 1 + .../Student/Resources/terraform/DEPLOY.md | 1 - .../Resources/terraform/generate_env_file.sh | 5 -- .../Student/Resources/terraform/main.tf | 12 ---- .../Student/Resources/terraform/main_azure.tf | 67 +++++++++---------- .../Resources/terraform/main_confluent.tf | 66 +----------------- .../Resources/terraform/main_outputs.tf | 16 ----- 36 files changed, 217 insertions(+), 357 deletions(-) delete mode 100644 074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh delete mode 100644 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json delete mode 100644 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json delete mode 100644 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json create mode 100644 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json create mode 100644 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json create mode 100644 074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json delete mode 100644 074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md create mode 100644 074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md delete mode 100644 074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh create mode 100644 074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md index 513b52ab13..758eab2454 100644 --- a/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/flink-sql/README.md @@ -2,7 +2,7 @@ ## Data Pipeline Overview The goal of the pipeline is to ensure that -- the data from the source data stores (Cosmos and Blob store) flows into Kafka topics +- the data from the source data stores (Cosmos DB) flows into Kafka topics - the data from the topics are joined and merged into transient tables - the data from the transient tables to finalized into the summary topics and tables - the data from the summary tables and pushed out to Azure AI search for the AI agent to use via MCP diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh index 7d0bf50eac..da2cdbe8f9 100644 --- a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/check_resources_status.sh @@ -8,18 +8,6 @@ print_lines() { echo "" } -print_lines -echo "Checking Azure Storage Account Shared Key Access..." -SHARED_KEY_ACCESS=$(az storage account show -g ${AZURE_RESOURCE_GROUP} --name ${STORAGE_ACCOUNT} --query "allowSharedKeyAccess" --output tsv) -echo "Shared Key Access: ${SHARED_KEY_ACCESS}" -echo "This should be 'true'" - -print_lines -echo "Checking Azure Storage Account Public Network Access..." -PUBLIC_NETWORK_ACCESS=$(az storage account show -g ${AZURE_RESOURCE_GROUP} --name ${STORAGE_ACCOUNT} --query "publicNetworkAccess" --output tsv) -echo "Public Network Access: ${PUBLIC_NETWORK_ACCESS}" -echo "This should be 'Enabled'" - print_lines echo "Checking Azure Cosmos DB Account Local Auth Disabled..." COSMOS_DB_DISABLE_LOCAL_AUTH=$(az cosmosdb show -g ${AZURE_RESOURCE_GROUP} --name ${COSMOS_DB_ACCOUNT} --query "disableLocalAuth" --output tsv) @@ -37,22 +25,6 @@ echo "" printf "%-45s %-12s %-12s %-10s\n" "Service Setting/Configuration" "Expected" "Actual" "Result" -# Azure Blob Storage Network Access -if [ "${PUBLIC_NETWORK_ACCESS}" == "Enabled" ]; then - result="Pass" -else - result="Fail" -fi -printf "%-45s %-12s %-12s %-10s\n" "Azure Blob Storage Network Access Enabled" "Enabled" "${PUBLIC_NETWORK_ACCESS}" "${result}" - -# Azure Blob Storage Shared Key -if [ "${SHARED_KEY_ACCESS}" == "true" ]; then - result="Pass" -else - result="Fail" -fi -printf "%-45s %-12s %-12s %-10s\n" "Azure Blob Storage Shared Key Allowed" "true" "${SHARED_KEY_ACCESS}" "${result}" - # Cosmos DB Public Network Access if [ "${COSMOS_DB_PUBLIC_NETWORK_ACCESS}" == "Enabled" ]; then result="Pass" diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh index 5c0875e0c8..02ad7b1682 100644 --- a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh +++ b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/environment-azure.sh @@ -3,5 +3,3 @@ export AZURE_RESOURCE_GROUP="confluent-hackathon" export COSMOS_DB_ACCOUNT="cfltizzya04qga" - -export STORAGE_ACCOUNT="cfltizzya04qga" \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh b/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh deleted file mode 100644 index 96a7c25169..0000000000 --- a/074-AIWithConfluentOnAzure/Coach/Solutions/maintenance_scripts/fix_azure_blob_store.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -source ./environment-azure.sh - -az storage account update -g ${AZURE_RESOURCE_GROUP} --name ${STORAGE_ACCOUNT} --allow-shared-key-access true - -az storage account update \ - --name ${STORAGE_ACCOUNT} \ - --resource-group ${AZURE_RESOURCE_GROUP} \ - --public-network-access Enabled \ - --default-action Allow - diff --git a/074-AIWithConfluentOnAzure/Student/Challenge-00.md b/074-AIWithConfluentOnAzure/Student/Challenge-00.md index 1044859552..1a2163b26d 100644 --- a/074-AIWithConfluentOnAzure/Student/Challenge-00.md +++ b/074-AIWithConfluentOnAzure/Student/Challenge-00.md @@ -52,8 +52,8 @@ In this challenge, you will: | Platform | Resource Provisioned | | ------------------- | ---------------------------------------------------------------------------------------------------------- | -| **Azure** | Azure OpenAI, Cosmos DB, Azure AI Search, Azure Redis Cache, Azure Storage Account | -| **Confluent Cloud** | Kafka Cluster, Schema Registry, Kafka topics, Cosmos DB & Blob Source connectors, AI Search Sink connector | +| **Azure** | Azure OpenAI, Cosmos DB, Azure AI Search, Azure Redis Cache | +| **Confluent Cloud** | Kafka Cluster, Schema Registry, Kafka topics, Cosmos DB Source connectors, AI Search Sink connector | | **AI Agents / MCP** | Deployment of microservices + MCP servers that expose capabilities to agents | ## Success Criteria @@ -61,7 +61,7 @@ In this challenge, you will: To complete this challenge successfully, you should be able to: - Verify Terraform deploys successfully and resources appear in Azure Portal and Confluent Cloud -- Verify source connectors are live and pushing data from Cosmos DB and Blob Storage into Kafka topics +- Verify source connectors are live and pushing data from Cosmos DB into Kafka topics - Verify sink connector is pushing data into Azure AI Search (net sales + net inventory count topics) - Demonstrate the MCP-powered AI agent can: - Respond when prompted diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh index 79b89fb790..3bf4ad013e 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-connectors.sh @@ -24,13 +24,10 @@ setup_confluent_connector() } -# Create the Kafka Source Connectors for Azure Blob Storage -setup_confluent_connector "azure_blob_departments" -setup_confluent_connector "azure_blob_product_pricing" -setup_confluent_connector "azure_blob_product_skus" - - -# Set up the Kafka Sink Connectors for Azure Cosmos DB +# Create the Kafka Source Connectors for Azure Cosmos DB +setup_confluent_connector "cosmos_db_departments" +setup_confluent_connector "cosmos_db_product_pricing" +setup_confluent_connector "cosmos_db_product_skus" setup_confluent_connector "cosmos_db_purchases" setup_confluent_connector "cosmos_db_returns" setup_confluent_connector "cosmos_db_replenishments" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh index 7dc64c53f3..405aea9691 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-create-topics.sh @@ -67,7 +67,7 @@ set_schema_registry_subject_compatibility() { } -# Reference topics from Azure Blob Store +# Reference topics from Azure Cosmos DB create_topic_with_schema "departments" create_topic_with_schema "product_pricing" create_topic_with_schema "product_skus" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh index fc0adfee01..1ae27401e9 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-connectors.sh @@ -6,7 +6,7 @@ # Function to get connector IDs from their names # Example usage: -# get_connector_ids "azure_blob_product_pricing_source_connector,azure_cosmos_db_purchases_source,azure_cosmos_db_returns_source" +# get_connector_ids "azure_cosmos_db_product_pricing_source,azure_cosmos_db_purchases_source,azure_cosmos_db_returns_source" get_connector_ids() { local connector_names_csv="$1" local connector_names_array @@ -42,7 +42,7 @@ echo "Deleting specified connectors from the cluster:" # These are the connector names to delete -connectors="ai_search_departments_sink,ai_search_net_sales_sink,ai_search_departments_flat_sink,ai_search_product_inventory_sink,azure_blob_product_pricing_source_connector,azure_cosmos_db_purchases_source,azure_blob_product_skus_source_connector,azure_cosmos_db_returns_source,azure_cosmos_db_replenishments_source,azure_blob_departments_source_connector" +connectors="ai_search_departments_sink,ai_search_net_sales_sink,ai_search_departments_flat_sink,ai_search_product_inventory_sink,azure_cosmos_db_product_pricing_source,azure_cosmos_db_purchases_source,azure_cosmos_db_product_skus_source,azure_cosmos_db_returns_source,azure_cosmos_db_replenishments_source,azure_cosmos_db_departments_source" # Call the function ids=$(get_connector_ids "$connectors") diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh index 53cb944851..1f4142955e 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-schemas.sh @@ -25,7 +25,7 @@ delete_topic_schemas() { confluent schema-registry schema list -# Reference topics from Azure Blob Store +# Reference topics from Azure Cosmos DB delete_topic_schemas "departments" delete_topic_schemas "product_pricing" delete_topic_schemas "product_skus" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh index 2eca130fc8..0a38f148ac 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-delete-topics.sh @@ -32,7 +32,7 @@ delete_kafka_topic_and_schemas() { echo "Topic $topic_name and its schemas have been deleted." } -# Reference topics from Azure Blob Store +# Reference topics from Azure Cosmos DB delete_kafka_topic_and_schemas "departments" delete_kafka_topic_and_schemas "product_pricing" delete_kafka_topic_and_schemas "product_skus" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh index b61167e90c..805dfb2e14 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-configs.sh @@ -38,9 +38,9 @@ connector_config_populate_secrets "ai_search_product_inventory" connector_config_populate_secrets "ai_search_net_sales" connector_config_populate_secrets "ai_search_departments_flat" -connector_config_populate_secrets "azure_blob_departments" -connector_config_populate_secrets "azure_blob_product_skus" -connector_config_populate_secrets "azure_blob_product_pricing" +connector_config_populate_secrets "cosmos_db_departments" +connector_config_populate_secrets "cosmos_db_product_skus" +connector_config_populate_secrets "cosmos_db_product_pricing" connector_config_populate_secrets "cosmos_db_purchases" connector_config_populate_secrets "cosmos_db_returns" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh index 3ce16fa741..6d423280b8 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/confluent-setup-populate-connector-reset.sh @@ -22,9 +22,9 @@ connector_config_reset "ai_search_product_inventory" connector_config_reset "ai_search_net_sales" connector_config_reset "ai_search_departments_flat" -connector_config_reset "azure_blob_departments" -connector_config_reset "azure_blob_product_skus" -connector_config_reset "azure_blob_product_pricing" +connector_config_reset "cosmos_db_departments" +connector_config_reset "cosmos_db_product_skus" +connector_config_reset "cosmos_db_product_pricing" connector_config_reset "cosmos_db_purchases" connector_config_reset "cosmos_db_returns" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json deleted file mode 100644 index 5ea3cffe94..0000000000 --- a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_departments.example.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "config": { - "connector.class": "AzureBlobSource", - "name": "azure_blob_departments_source_connector", - "topic.regex.list": "departments:.*", - "schema.context.name": "default", - "kafka.auth.mode": "KAFKA_API_KEY", - "kafka.api.key": "[KAFKA_API_KEY]", - "kafka.api.secret": "[KAFKA_API_SECRET]", - "azblob.account.name": "[AZURE_STORAGE_ACCOUNT_NAME]", - "azblob.account.key": "[AZURE_STORAGE_ACCOUNT_KEY]", - "azblob.container.name": "departments", - "azblob.retry.type": "EXPONENTIAL", - "input.data.format": "JSON", - "output.data.format": "JSON", - "topics.dir": "topics", - "directory.delim": "/", - "behavior.on.error": "FAIL", - "format.bytearray.separator": "\n", - "task.batch.size": "10", - "file.discovery.starting.timestamp": "0", - "azblob.poll.interval.ms": "60000", - "record.batch.max.size": "200", - "tasks.max": "1", - "value.converter.decimal.format": "BASE64", - "value.converter.replace.null.with.default": "true", - "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", - "value.converter.schemas.enable": "false", - "errors.tolerance": "none", - "value.converter.value.subject.name.strategy": "TopicNameStrategy", - "key.converter.key.subject.name.strategy": "TopicNameStrategy", - "value.converter.ignore.default.for.nullables": "false", - "auto.restart.on.user.error": "true" - } - } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json deleted file mode 100644 index 52ef7e784d..0000000000 --- a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_pricing.example.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "config": { - "connector.class": "AzureBlobSource", - "name": "azure_blob_product_pricing_source_connector", - "topic.regex.list": "product_pricing:.*", - "schema.context.name": "default", - "kafka.auth.mode": "KAFKA_API_KEY", - "kafka.api.key": "[KAFKA_API_KEY]", - "kafka.api.secret": "[KAFKA_API_SECRET]", - "azblob.account.name": "[AZURE_STORAGE_ACCOUNT_NAME]", - "azblob.account.key": "[AZURE_STORAGE_ACCOUNT_KEY]", - "azblob.container.name": "product-pricing", - "azblob.retry.type": "EXPONENTIAL", - "input.data.format": "JSON", - "output.data.format": "JSON", - "topics.dir": "topics", - "directory.delim": "/", - "behavior.on.error": "FAIL", - "format.bytearray.separator": "\n", - "task.batch.size": "10", - "file.discovery.starting.timestamp": "0", - "azblob.poll.interval.ms": "60000", - "record.batch.max.size": "200", - "tasks.max": "1", - "value.converter.decimal.format": "BASE64", - "value.converter.replace.null.with.default": "true", - "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", - "value.converter.schemas.enable": "false", - "errors.tolerance": "none", - "value.converter.value.subject.name.strategy": "TopicNameStrategy", - "key.converter.key.subject.name.strategy": "TopicNameStrategy", - "value.converter.ignore.default.for.nullables": "false", - "auto.restart.on.user.error": "true" - } - } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json deleted file mode 100644 index 703b8fb105..0000000000 --- a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/azure_blob_product_skus.example.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "config": { - "connector.class": "AzureBlobSource", - "name": "azure_blob_product_skus_source_connector", - "topic.regex.list": "product_skus:.*", - "schema.context.name": "default", - "kafka.auth.mode": "KAFKA_API_KEY", - "kafka.api.key": "[KAFKA_API_KEY]", - "kafka.api.secret": "[KAFKA_API_SECRET]", - "azblob.account.name": "[AZURE_STORAGE_ACCOUNT_NAME]", - "azblob.account.key": "[AZURE_STORAGE_ACCOUNT_KEY]", - "azblob.container.name": "product-skus", - "azblob.retry.type": "EXPONENTIAL", - "input.data.format": "JSON", - "output.data.format": "JSON", - "topics.dir": "topics", - "directory.delim": "/", - "behavior.on.error": "FAIL", - "format.bytearray.separator": "\n", - "task.batch.size": "10", - "file.discovery.starting.timestamp": "0", - "azblob.poll.interval.ms": "60000", - "record.batch.max.size": "200", - "tasks.max": "1", - "value.converter.decimal.format": "BASE64", - "value.converter.replace.null.with.default": "true", - "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", - "value.converter.schemas.enable": "false", - "errors.tolerance": "none", - "value.converter.value.subject.name.strategy": "TopicNameStrategy", - "key.converter.key.subject.name.strategy": "TopicNameStrategy", - "value.converter.ignore.default.for.nullables": "false", - "auto.restart.on.user.error": "true" - } - } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json new file mode 100644 index 0000000000..c7fae74390 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_departments.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_departments_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "departments#departments", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json new file mode 100644 index 0000000000..82d153537d --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_pricing.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_product_pricing_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "product_pricing#product_pricing", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } diff --git a/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json new file mode 100644 index 0000000000..f11e8d20d8 --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/connector-configurations/cosmos_db_product_skus.example.json @@ -0,0 +1,27 @@ +{ + "config": { + "connector.class": "CosmosDbSource", + "name": "azure_cosmos_db_product_skus_source", + "schema.context.name": "default", + "kafka.auth.mode": "KAFKA_API_KEY", + "kafka.api.key": "[KAFKA_API_KEY]", + "kafka.api.secret": "[KAFKA_API_SECRET]", + "connect.cosmos.connection.endpoint": "https://[AZURE_COSMOS_DB_ACCOUNT_NAME].documents.azure.com:443/", + "connect.cosmos.master.key": "[AZURE_COSMOS_DB_ACCOUNT_KEY]", + "connect.cosmos.databasename": "[AZURE_COSMOS_DB_DATABASE_NAME]", + "connect.cosmos.containers.topicmap": "product_skus#product_skus", + "connect.cosmos.task.timeout": "5000", + "connect.cosmos.task.buffer.size": "10000", + "connect.cosmos.task.batch.size": "100", + "connect.cosmos.task.poll.interval": "1000", + "output.data.format": "JSON_SR", + "connect.cosmos.messagekey.enabled": "true", + "connect.cosmos.messagekey.field": "id", + "tasks.max": "1", + "auto.restart.on.user.error": "true", + "value.converter.decimal.format": "BASE64", + "value.converter.reference.subject.name.strategy": "DefaultReferenceSubjectNameStrategy", + "value.converter.value.subject.name.strategy": "TopicNameStrategy", + "key.converter.key.subject.name.strategy": "TopicNameStrategy" + } + } diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md deleted file mode 100644 index c68abe83da..0000000000 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_BLOB_STORE_CONTENTS.md +++ /dev/null @@ -1,19 +0,0 @@ -### Uploading Blob Store Contents - -We can use the following steps to upload the blob store contents. First you will need to login to the Azure CLI. - -````bash - -az login - -```` - -#### Batch File Uploads - -We can upload the departments, product_pricing and product_skus dataset using the following Azure CLI commands: - -````bash - - - -```` \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md new file mode 100644 index 0000000000..e51a16bc0e --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/UPLOADING_COSMOS_DB_CONTENTS.md @@ -0,0 +1,23 @@ +### Uploading Cosmos DB Contents + +We can use the following steps to upload the Cosmos DB container contents. First you will need to login to the Azure CLI. + +````bash + +az login + +```` + +#### Batch Document Uploads + +We can upload the departments, product_pricing and product_skus datasets to Cosmos DB using the Azure CLI commands. The script `azure_cosmos_upload.sh` automates this process. + +Make sure you have set the required environment variables: +- `AZURE_COSMOS_DB_ACCOUNT_NAME`: The name of your Cosmos DB account +- `AZURE_COSMOS_DB_DATABASE_NAME`: The name of your Cosmos DB database (typically "retailstore") + +Then run: + +````bash +./azure_cosmos_upload.sh +```` \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh deleted file mode 100644 index 92d0a0c5bc..0000000000 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_blob_upload.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# Function to upload files to blob store -upload_to_blob_storage() { - - STORAGE_ACCOUNT_NAME="${AZURE_STORAGE_ACCOUNT_NAME}" - - TARGET_FOLDER=$1 - - DESTINATION_CONTAINER="${TARGET_FOLDER//_/-}" - - echo "Uploading Files from ${TARGET_FOLDER} to ${STORAGE_ACCOUNT_NAME} ..." - - echo "Changing directory to ${TARGET_FOLDER}" - cd ${TARGET_FOLDER} - - echo "Uploading JSON files to Azure Blob Storage Account ${STORAGE_ACCOUNT_NAME}/${DESTINATION_CONTAINER}/topics ..." - - az storage blob upload-batch \ - --account-name "${STORAGE_ACCOUNT_NAME}" \ - --account-key "${AZURE_STORAGE_ACCOUNT_KEY}" \ - --destination "${DESTINATION_CONTAINER}/topics" \ - --source . \ - --overwrite \ - --pattern "*.json" - - - echo "Upload completed." - - cd .. - -} - -upload_to_blob_storage "departments" -upload_to_blob_storage "product_pricing" -upload_to_blob_storage "product_skus" - -echo "All uploads completed." diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh new file mode 100644 index 0000000000..0c8817c2cf --- /dev/null +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/azure_cosmos_upload.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Function to upload files to Cosmos DB +upload_to_cosmos_db() { + + COSMOS_DB_ACCOUNT_NAME="${AZURE_COSMOS_DB_ACCOUNT_NAME}" + COSMOS_DB_DATABASE_NAME="${AZURE_COSMOS_DB_DATABASE_NAME}" + + TARGET_FOLDER=$1 + CONTAINER_NAME="${TARGET_FOLDER//_/-}" + + echo "Uploading Files from ${TARGET_FOLDER} to Cosmos DB container ${CONTAINER_NAME} ..." + + echo "Changing directory to ${TARGET_FOLDER}" + cd ${TARGET_FOLDER} + + echo "Uploading JSON files to Cosmos DB Account ${COSMOS_DB_ACCOUNT_NAME}/${COSMOS_DB_DATABASE_NAME}/${CONTAINER_NAME} ..." + + # Loop through all JSON files in the current directory + for file in *.json; do + if [ -f "$file" ]; then + echo "Uploading $file to Cosmos DB container ${CONTAINER_NAME}..." + + # Use az cosmosdb sql container item create to upload the document + az cosmosdb sql container item create \ + --account-name "${COSMOS_DB_ACCOUNT_NAME}" \ + --database-name "${COSMOS_DB_DATABASE_NAME}" \ + --container-name "${CONTAINER_NAME}" \ + --item "@${file}" \ + --output none + + if [ $? -eq 0 ]; then + echo "✅ Successfully uploaded $file" + else + echo "❌ Failed to upload $file" + fi + fi + done + + echo "Upload completed for ${CONTAINER_NAME}." + + cd .. + +} + +upload_to_cosmos_db "departments" +upload_to_cosmos_db "product_pricing" +upload_to_cosmos_db "product_skus" + +echo "All uploads completed." diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json index 3faee78a40..aa3dc59655 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/appliance.json @@ -1,4 +1,5 @@ { + "id": "appliance", "department": "appliance", "description": "The appliance department is where we have simple use electronics for the home but mostly for the kitchen area. This is the only department were returned items can count towards the available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json index 6afb38f0bd..beb188379f 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/cleaning.json @@ -1,4 +1,5 @@ { + "id": "cleaning", "department": "cleaning", "description": "This is where we find cleaning supplies. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json index e76e02da7c..02c9ccbfe1 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/dairy.json @@ -1,4 +1,5 @@ { + "id": "dairy", "department": "dairy", "description": "The dairy department where we find products like cheese, milk, butter and other dairy items. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json index 916f559dde..f8f8aab979 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/deli.json @@ -1,4 +1,5 @@ { + "id": "deli", "department": "deli", "description": "This is where we find cooked food and other ready-to-eat meals. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json index 8ae9dc22dc..fc5ad4a9be 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/meat.json @@ -1,4 +1,5 @@ { + "id": "meat", "department": "meat", "description": "This is where we find meats such as chicken, pork, beef, lamb etc. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json index 9cd81c200c..c4bae15a9b 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/pharmacy.json @@ -1,4 +1,5 @@ { + "id": "pharmacy", "department": "pharmacy", "description": "This is where we find pharmaceutical items like medications and first aid kits. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json index af785f89ca..b8abac516f 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/produce.json @@ -1,4 +1,5 @@ { + "id": "produce", "department": "produce", "description": "The produce departments is where we find fresh fruits and vegatables. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json index 2a3f9097c2..fa10c34eea 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json +++ b/074-AIWithConfluentOnAzure/Student/Resources/retail_store/departments/seafood.json @@ -1,4 +1,5 @@ { + "id": "seafood", "department": "seafood", "description": "This is the department where we find seafood products. Items returned from this department do not count towards available inventory numbers." } \ No newline at end of file diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md b/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md index 0f01a2b1fa..295889f2d1 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/DEPLOY.md @@ -97,7 +97,6 @@ terraform apply If you included the `output` blocks (like I did in the Terraform file earlier), after `apply`, Terraform will print the important connection details: ✅ Cosmos DB endpoint -✅ Storage account blob URL ✅ Redis hostname and access key ✅ Azure Search keys diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh b/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh index a81f407f3e..c88ae25860 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/generate_env_file.sh @@ -29,11 +29,6 @@ terraform output -raw search_service_name | awk '{print "export AZURE_SEARCH_SER terraform output -raw azure_search_admin_key | awk '{print "export AZURE_SEARCH_API_KEY=\"" $0 "\""}' >> "$ENV_FILE" echo "" >> "$ENV_FILE" -echo "# Azure Storage Account Credentials" >> "$ENV_FILE" -terraform output -raw storage_account_name | awk '{print "export AZURE_STORAGE_ACCOUNT_NAME=\"" $0 "\""}' >> "$ENV_FILE" -terraform output -raw storage_account_primary_access_key | awk '{print "export AZURE_STORAGE_ACCOUNT_KEY=\"" $0 "\""}' >> "$ENV_FILE" -echo "" >> "$ENV_FILE" - #echo "# Azure Redis Cache Credentials" >> "$ENV_FILE" #terraform output -raw redis_hostname | awk '{print "export REDIS_HOSTNAME=\"" $0 "\""}' >> "$ENV_FILE" #terraform output -raw redis_primary_access_key | awk '{print "export REDIS_PRIMARY_ACCESS_KEY=\"" $0 "\""}' >> "$ENV_FILE" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf index c31aef6c6b..5947bcf9b8 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main.tf @@ -116,18 +116,6 @@ variable "kafka_partitions_count" { # ----------------- # Connector Maps # ----------------- -variable "blob_store_connectors" { - description = "Blob source connectors map" - type = map(object({ - name = string - topic = string - container = string - })) - default = {} -} - - - variable "cosmos_db_connectors" { description = "Cosmos DB source connectors map" type = map(object({ diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf index e56b2b5828..0c8cc8c6ed 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_azure.tf @@ -4,36 +4,6 @@ resource "azurerm_resource_group" "main" { location = var.resource_group_location } - - -resource "azurerm_storage_account" "storage" { - name = "${var.name_prefix}sa" - resource_group_name = azurerm_resource_group.main.name - location = azurerm_resource_group.main.location - account_tier = "Standard" - account_replication_type = "ZRS" - account_kind = "StorageV2" - public_network_access_enabled = true - shared_access_key_enabled = true -} - -# Define a list of blob container names -locals { - container_names = [ - "departments", - "product-pricing", - "product-skus" - ] -} - -# Create containers using a loop -resource "azurerm_storage_container" "containers" { - for_each = toset(local.container_names) - name = each.value - storage_account_id = azurerm_storage_account.storage.id - container_access_type = "private" -} - # Azure AI Search Instance # New changes to the Azure Search Service API require the use of # `local_authentication_enabled` and `authentication_failure_mode` properties. @@ -51,8 +21,6 @@ resource "azurerm_search_service" "search" { local_authentication_enabled = true authentication_failure_mode = "http403" public_network_access_enabled = true - - depends_on = [ azurerm_storage_container.containers ] } # Azure Cosmos DB (SQL API) @@ -74,8 +42,6 @@ resource "azurerm_cosmosdb_account" "cosmosdb" { location = azurerm_resource_group.main.location failover_priority = 0 } - - depends_on = [ azurerm_storage_container.containers ] } # Cosmos DB SQL Database @@ -120,6 +86,39 @@ resource "azurerm_cosmosdb_sql_container" "replenishments" { throughput = 400 } +# Departments Container +resource "azurerm_cosmosdb_sql_container" "departments" { + name = "departments" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/department"] + throughput = 400 +} + +# Product Pricing Container +resource "azurerm_cosmosdb_sql_container" "product_pricing" { + name = "product_pricing" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/sku_id"] + throughput = 400 +} + +# Product SKUs Container +resource "azurerm_cosmosdb_sql_container" "product_skus" { + name = "product_skus" + resource_group_name = azurerm_resource_group.main.name + account_name = azurerm_cosmosdb_account.cosmosdb.name + database_name = azurerm_cosmosdb_sql_database.retailstore.name + + partition_key_paths = ["/sku_id"] + throughput = 400 +} + # Azure Redis Cache resource "azurerm_redis_cache" "redis" { name = "${var.name_prefix}redis" diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf index 3aa2aa5866..95348229c6 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_confluent.tf @@ -81,69 +81,6 @@ resource "confluent_schema" "value_schemas" { depends_on = [ confluent_schema_registry_cluster_config.microsoft_hackathon ] } -# Create the Source Connectors for Azure Blob Storage -resource "confluent_connector" "blob_store_connectors" { - - for_each = var.blob_store_connectors - - environment { - id = var.confluent_environment_id - } - - kafka_cluster { - id = var.kafka_id - } - - config_sensitive = { - "azblob.account.key" = azurerm_storage_account.storage.primary_access_key - } - - config_nonsensitive = { - "azblob.account.name" = azurerm_storage_account.storage.name - "connector.class" = "AzureBlobSource" - "name" = each.value.name - "topic.regex.list" = each.value.topic - "schema.context.name" = "default" - "kafka.auth.mode" = "SERVICE_ACCOUNT" - "kafka.service.account.id" = var.kafka_service_account_id - "azblob.container.name" = each.value.container - "azblob.retry.type" = "EXPONENTIAL" - "input.data.format" = "JSON" - "output.data.format" = "JSON" - "topics.dir" = "topics" - "directory.delim" = "/" - "behavior.on.error" = "FAIL" - "format.bytearray.separator" = "\n" - "task.batch.size" = "10" - "file.discovery.starting.timestamp" = "0" - "azblob.poll.interval.ms" = "60000" - "record.batch.max.size" = "200" - "tasks.max" = "1" - "value.converter.decimal.format" = "BASE64" - "value.converter.replace.null.with.default" = "true" - "value.converter.reference.subject.name.strategy" = "DefaultReferenceSubjectNameStrategy" - "value.converter.schemas.enable" = "false" - "errors.tolerance" = "none" - "value.converter.value.subject.name.strategy" = "TopicNameStrategy" - "key.converter.key.subject.name.strategy" = "TopicNameStrategy" - "value.converter.ignore.default.for.nullables" = "false" - "auto.restart.on.user.error" = "true" - } - - depends_on = [ - azurerm_storage_account.storage, - azurerm_storage_container.containers, - confluent_kafka_topic.topics, - confluent_schema.key_schemas, - confluent_schema.value_schemas - ] - - lifecycle { - prevent_destroy = false - } -} - - # Create the Source Connectors for Azure Cosmos DB resource "confluent_connector" "cosmos_db_connectors" { for_each = var.cosmos_db_connectors @@ -191,6 +128,9 @@ resource "confluent_connector" "cosmos_db_connectors" { azurerm_cosmosdb_sql_container.purchases, azurerm_cosmosdb_sql_container.returns, azurerm_cosmosdb_sql_container.replenishments, + azurerm_cosmosdb_sql_container.departments, + azurerm_cosmosdb_sql_container.product_pricing, + azurerm_cosmosdb_sql_container.product_skus, confluent_kafka_topic.topics, confluent_schema.key_schemas, confluent_schema.value_schemas diff --git a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf index 8de801902d..3a6c9b42c4 100644 --- a/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf +++ b/074-AIWithConfluentOnAzure/Student/Resources/terraform/main_outputs.tf @@ -47,21 +47,5 @@ output "azure_search_endpoint" { value = azurerm_search_service.search.name } -output "storage_account_name" { - description = "The name of the storage account" - value = azurerm_storage_account.storage.name -} - -output "storage_account_primary_access_key" { - description = "Primary Access Key for Azure Storage Account" - value = azurerm_storage_account.storage.primary_access_key - sensitive = true -} - -output "storage_account_blob_endpoint" { - description = "Blob service endpoint for the storage account" - value = azurerm_storage_account.storage.primary_blob_endpoint -} -