Wednesday, December 7, 2022

Are you ready to solve Christmas-themed programming puzzles? Advent Of Code 2022 is live!

Vibin' with AoC 

I came upon a piece by Herbert Daly a few days ago when browsing my LinkedIn feed. I read the description of a puzzle in the photo that was uploaded with the post since it was intriguing. The puzzle's focus on the holiday season and Christmas kept me interested. I dug more after that and discovered Advent of Code (often referred using its acronym, AoC). I just felt good about AoC and the theme behind it. It is the sole reason behind my inspiration to reactivate this blog after it had been dormant for months.


What is Advent Of Code? 

Advent of Code is series of Christmas-themed programming puzzles that is released one at each day between December 1st and December 25th. Each puzzle consists of two parts; the second portion, which is typically a setting established by the first half of the puzzle, is disclosed after the first part has been solved. You receive a Star ⭐ for each part of the puzzle you successfully solve. Over the course of a season, up to 50 stars can be earned. You can use any programming language of your choice to solve the puzzles. A point system is available to score the players according to how long it takes them to finish the puzzles. On a leaderboard that is accessible through the website, the top 100 players are distributed. There's even a wonderful Advent calendar that list the days 1 to 25 arranged from bottom to top. A Christmas-themed artwork is hidden behind a sequence of @'s and #'s on the Calendar. As you complete a puzzle each day, the artwork is exposed one piece at a time.

Advent Calendar for 2022


Eric Wastl introduced Advent of Code on December 1, 2015. The eighth edition, Advent of Code 2022, is now available! The website still allows the users to solve the puzzles of previous years. 

What is in it for Mainframers?

When I first entered the website of AoC, I had a feeling of familiarity with the look because it appeared like a Mainframe screen. I (selfishly) assumed  that the site and theme were designed for Mainframers, but I was mistaken. The puzzles are available to everyone, including those with limited programming experience and problem-solving abilities.

Nonetheless, AoC has a lot to offer for Mainframers.  All the puzzles can be solved using Mainframe programming languages such as COBOL, REXX, ICETOOL/DFSORT, and so on. There is even a private leaderboard where you may compete with other Mainframers. Continue reading to learn how to join up for AoC and the exclusive leaderboard for Mainframers.

Signing up for AoC and the exclusive leaderboard for Mainframers

To begin solving the puzzles, you must first register with AoC. You may sign up using either of the following accounts by clicking here.
  • GitHub
  • Google
  • Twitter
  • Reddit 
questionnaire must be completed in order to join the exclusive private Leaderboard for Mainframers. After submitting the form, a secret code will be sent to you through email. Simply copy the code and go to https://adventofcode.com/2022/leaderboard/private to join the board. 

Herbert Daly and Henri Kuiper, two Mainframe enthusiasts, maintain the private leaderboard. They've even stated that some folks at MicroFocus will be supporting the private leaderboard (again!) by providing some awesome swag and prizes to those who solve this year's tasks using the language that runs the world: COBOL.

"HELP will always be given at Hogwarts to those who ask for it" - Albus Dumbledore

If you get stuck when solving the puzzles, feel free to join these Subreddits and ask for hints.
I've started adding the code for each day's puzzle to my Git repository. At the time of writing this post, code till Day 6 puzzles are available on the Git. You may use them as a reference material.  

I even intend to write a post every day until December 25th to walk through my approach to tackling these puzzles. 

So, what are you waiting for 🤔? See you (your name) on the Leaderboard 👍

If you have any queries about the content of this page, please leave them in the Comments area below.


Thursday, April 7, 2022

My takeaway from SHARE Dallas 2022 Hackathon for IBM Z - Part 1

Hiya! 👋

It's been some time since I wrote on my blog. Recently, I participated in SHARE Dallas 2022 Hackathon that happened between Mar 28, 2022 and Mar 29, 2022 and it was a great experience that I wanted to treasure. Hence this post 😀.

This Hackathon showed the modern ways of working on a Mainframe and it, for sure, fascinates the Mainframers as well as those who think of IBM Mainframes as legacy and old stuff.   

⚠ Before we start, I would like to let you know that this is going to be a long post because the takeaway was pretty huge for me. So, I'll be writing couple of posts to cover the entire experience (this being the first one)

The Hackathon was made available to participate for virtual attendees as well as in-person attendees of SHARE Dallas 2022 Event and no registration cost was involved. I participated virtually from India. 

How things began on the day of event? 

I received an email from the Hackathon's organizers with instructions to install the necessary tools  (given below): 

Discord - Most of the communication with organizers and fellow Hackers took place on Discord. 

VSCode with Zowe Explorer extension - This is an IDE. Zowe Explorer extension on VSCode was used throughout the Hackathon to interact with Mainframe and even with an IoT device. 

Postman - This tool allows to easily test and call REST-based APIs and web-enabled microservices. Though this tool was optional to install, I had it installed on my system and used it to GET and POST some API's. This gave an outlook on the structure of response after posting a request (more about this in the later part of this post) 

OpenVPN - The Hackathon wanted our personal system to be connected to the Montpellier VPN to access the Mainframe. 

In another email from the Organizers, I received my Credentials for the VPN and Z System. There was also a link provided in the same email to access the Challenge documentation. 

I just grabbed a coffee 🥤 and started reading out the 40 page Challenge documentation. 

The Challenge 💪

We were walked through the Catalog Manager Application running inside CICS and written in COBOL. The application had three basic functions:
  • Display all the items in a catalog 
  • Display detailed information of an item
  • Order an item.
There were some screenshots on the documentation which showed the CICS Screen interface to access the Catalog Manager application and its functionalities.

CICS Interface showing the Main Menu of the Catalog Manager Application.

CICS Interface showing the list of items in the Catalog, when '1. List Items' is selected from the Main Menu.

CICS Interface showing the detailed information of an item when an item is selected from the previous screen. 

CICS Interface showing the status of the order at the left side bottom of the screen. 

The overall challenge was to re-build this application using Python on z/OS and REST API's. The transactions still be handled by the CICS Transaction sever as they had enabled a technology (z/OS Connect Enterprise Edition) on the Hackathon LPAR to make the CICS functions available by means of REST API's. Don't fret if all these jargons doesn't make too much sense right now. You'll understand once they are unfolded in the later part of this post. 

Hacking through the tasks for Day 1

Task 1:

After connecting to the Montpellier VPN and setting up the profile for Hackathon in Zowe Explorer on VS Code, I started doing the first task, which was to implement the Traditional "Hello World" application. I used the Terminal to type Unix commands to create a new file (helloWorld.py) on the home directory of Unix System Services. 
There is a UNIX interface within z/OS called UNIX System Services, or USS, so you can log in through ssh and hammer out commands.

For writing the Python code, I used the IBM Z Open Editor instead of Unix terminal. To view/edit the files on IBM Z Open Editor, all you need to do is to locate the file that you just created, from Unix System Services (USS) section under Zowe, and click on it. The contents of the file will be shown on the right side on IBM Z Open Editor. 

Viewing the contents of helloWorld.py file on IBM X Open Editor.

I just wrote a one line command using the print() function in Python to display a message. To finish the Task 1, I used the python3 command on the Terminal of VS Code to run the Python script I had created. 

Output displayed after invoking the Python script using python3 command from USS Terminal.

It is essential that we get inside the directory where our Python code is saved, before running the code with the python3 command. 

This marked the completion of Task 1 ✅ 

Task 2:

To take things to the next level, Task 2 was all about creating our First web application on z/OS. I was introduced to the usage of Flask on Python. 

Flask is a popular web framework and it provides functions on Python for rendering an HTML page and handling incoming HTTP requests. 

I installed Flask on Python using the pip3 command. Post installation, I created a new directory under my Home directory (/u/ztecu85) and named it as webApp. Under webApp directory, two sub-directories namely static and templates were created. 

webApp directory is where all my project's files resided. As the challenge unfolded, we had to create some HTML files and those were stored under the templates sub directory. 

To complete the task, I created a new file named as webserver.py under webApp directory and wrote the code as shown below. 


Let me walk you through some of the important sections of this code.

from flask import Flask - This line imports Flask module to the project. 

app = Flask(__name__) - __name__ is a special variable in Python which returns the name of the current module (webserver.py).  This line of code helps Flask look for the relevant files needed by the application, such as static and template files. Flask manages to find the root path based on the value stored in __name__

@app.route('/') - This tells the Flask which URL should call the user defined Python function, index()that is defined in the next line. By passing '/' as an argument to the route() function of the Flask Class, we're binding the URL so that when we load the URL on the browser, we will be greeted with a message returned by index() function. 

As we have associated the URL - 10.3.20.138 and Port - 24320 with the index() function defined in Python through app.run() method, this 👇 is what happened when I ran this code from the Unix Terminal. 


Upon the execution of the code, there were several messages shown on the Terminal. One message showed a URL where the application was running. Pressing Ctrl + Clicking on the link took me to the URL where the message returned by the index() function was displayed. 

This task was a nice twist to the traditional 'Hello World' program that we printed the same message on a web application. 

Task 3: 

This task introduced me to the CICS part. As mentioned earlier, the three CICS functions were made available to us by means of three REST API's. The Challenge documentation for this task contained a table with detailed description of the API's. 

Though testing these API's were optional, I used the Postman tool to post the API's with the URL given for each function and receive responses to get familiarized with them. 

Following are the GIF's showing the responses received on Postman after posting the three API's. 

1. API to list all the items in Catalog

HTTP Verb:  GET

URL given to access this service: http://10.3.20.1:50780/catalogManager/v1.0/items?startItemRef={ }

Note that there were 21 items in the Catalog and each item had a unique Item Reference number (itemRef), starting from # 0010 up until 0210, in the increment of +10. The curly braces (highlighted in Red color) at the end of the URL means that it accepts a query parameter, which is an Integer between 10 and 210 (in the increment of +10). In the following GIF, I've assigned 10 to startItemRef at the end of the URL, so that the CICS application use the startItemRef value to get the next 15 items from the Catalog. 



2. API to get the detailed information on one Item:

HTTP Verb: GET

URL given to access this service: http://10.3.20.1:50780/catalogManager/v1.0/items/{ }

Posting this URL fetched the detailed information on one Item with itemRef that we have passed as query parameter at the end of the URL (The curly braces highlighted in Red color at the end of the URL means that it accepts query parameter). 



3. API to Order an Item:

HTTP Verb: POST

URL given to access this service: http://10.3.20.1:50780/catalogManager/v1.0/orders 

This service was different from the other two that while posting this service, we had to send along a Request in JSON format. This Request contained information about the item that we wish to order and the User ID with which we are ordering. CICS Application used this information to update the Catalog and pass the Order's status message. 

Upon posting the URL, following response was received.  


Task 3a:

In this task, we were asked to invoke the API, that list items from the Catalog, using Python. As the response had only 15 items, participants were asked to use the information in the lastItemRef key to create some code in Python that lists all 21 items. FYI, each Item in the response would have a lastItemRef key that holds the value of the last item's reference number. So, the idea was to post the API and get the first response. Then, make use of the lastItemRef key value from the 15th item of the first response and use this value as a query parameter and create the URL to be posted for the second response. 

It was required to combine the two results from the API calls. A clue that was given to the participants was to convert the responses into a Python Dictionary with the json() method; then add two dictionaries together using the extend() method. 

This is where I got stuck 😕 and couldn't get past this task on the Day 1. I slept over this problem and was able to fare better on the Day 2.

Hacking through the tasks for Day 2

Task 3a (continued): 

The response after posting the  API to list the items in the Catalog looked like the below:

 {  
   "data": {  
     "returnCode": 0,  
     "responseMessage": "+15 ITEMS RETURNED",  
     "inquireCatalog": {  
       "startItemRef": 10,  
       "lastItemRef": 150,  
       "items": [  
         {  
           "itemRef": 10,  
           "cost": "089.90",  
           "onOrder": 0,  
           "description": "Man's Waterproof Rain Jacket",  
           "department": 10,  
           "stock": 989  
         },  
         {  
           "itemRef": 20,  
           "cost": "089.90",  
           "onOrder": 99,  
           "description": "Women Waterproof Rain Jacket",  
           "department": 10,  
           "stock": 996  
         },  
         {  
           "itemRef": 30,  
           "cost": "040.90",  
           "onOrder": 0,  
           "description": "Sunglasses",  
           "department": 10,  
           "stock": 992  
         },  
         {  
           "itemRef": 40,  
           "cost": "079.90",  
           "onOrder": 0,  
           "description": "Windy Umbrella",  
           "department": 10,  
           "stock": 996  
         },  
         {  
           "itemRef": 50,  
           "cost": "004.99",  
           "onOrder": 0,  
           "description": "Hot Coffee",  
           "department": 10,  
           "stock": 990  
         },  
         {  
           "itemRef": 60,  
           "cost": "004.99",  
           "onOrder": 40,  
           "description": "Hot Chocolate",  
           "department": 10,  
           "stock": 999  
         },  
         {  
           "itemRef": 70,  
           "cost": "049.99",  
           "onOrder": 20,  
           "description": "Woman swim suit with fancy colors",  
           "department": 10,  
           "stock": 992  
         },  
         {  
           "itemRef": 80,  
           "cost": "049.99",  
           "onOrder": 0,  
           "description": "Man's swim suit also with fancy colors",  
           "department": 10,  
           "stock": 998  
         },  
         {  
           "itemRef": 90,  
           "cost": "019.99",  
           "onOrder": 0,  
           "description": "Thermoflask double stainless steel",  
           "department": 10,  
           "stock": 996  
         },  
         {  
           "itemRef": 100,  
           "cost": "009.90",  
           "onOrder": 20,  
           "description": "Icecream Family Pack",  
           "department": 10,  
           "stock": 994  
         },  
         {  
           "itemRef": 110,  
           "cost": "004.40",  
           "onOrder": 0,  
           "description": "Iced Tea",  
           "department": 10,  
           "stock": 995  
         },  
         {  
           "itemRef": 120,  
           "cost": "025.99",  
           "onOrder": 0,  
           "description": "Mineral Sunscreen",  
           "department": 10,  
           "stock": 997  
         },  
         {  
           "itemRef": 130,  
           "cost": "014.85",  
           "onOrder": 0,  
           "description": "Rain Cap Size Small",  
           "department": 10,  
           "stock": 998  
         },  
         {  
           "itemRef": 140,  
           "cost": "014.85",  
           "onOrder": 0,  
           "description": "Rain Cap Size Medium",  
           "department": 10,  
           "stock": 999  
         },  
         {  
           "itemRef": 150,  
           "cost": "014.85",  
           "onOrder": 45,  
           "description": "Rain Cap Size Large",  
           "department": 10,  
           "stock": 996  
         }  
       ]  
     }  
   }  
 }  

Per Python, this data is structured as a nested Dictionary. 

💡 Python Dictionaries store data values in key:value pair and are written with Curly braces. 

"data" is a dictionary with three key:value pairs viz. "returnCode", "responseMessage" and "inquireCatalog". 

"inquireCatalog" itself is a Dictionary with three key:value pairs (again 😐). Make note of the third key, "items" for the value of this key is a Python List of all the 15 items of the response. 

💡 Python Lists are created using square brackets and are used to store multiple items in a single variable. 

Responses from the two API calls resulted in two Python Dictionaries but I was not able to combine these dictionaries together. 

Discord came as savior 🙏. I posted this issue there and the organizers quickly helped me understand that most of the info from the Dictionary won't be used besides to make sure the request went well and the focus should be only on the Python List with the details of the items in the Catalog. 

I created a new file named as webRequestHandler.py under the webApp directory and wrote the following code to get the result needed to mark this task as complete ✅.


I've added comments to each line of the code for your understanding. Still, I would like to highlight few sections of the code. 

Line #13 is used to create a Python dictionary called header which stores the authentication token given by the Organizers of Hackathon. Requests to the back-end systems only with this Auth token are deemed as legal. Without the Auth token, we will not be able to send/post API's and get the responses from the back-end systems. 

This 👇 is what happened after running this Python script. 



The output was a Python List of all the 21 items that were on the Catalog and this marked the task as complete ✅.


In the next task, we will make this response look nicer 👌 using Flask HTML rendering capabilities. 

I'm hitting the pause button on this experience journey for now. Remaining tasks will be covered on the next post titled as "My takeaway from SHARE Dallas 2022 Hackathon for IBM Z - Part 2". Keep watching this space 👀

Thanks for reading! Should you have any questions/feedback, please post them in Comments section below. 


References:
1. Challenge Documentation provided for the Hackathon. 
2. GeeksforGeeks, Programiz and W3Schools for Python related information.

Screenshot/GIF courtesy: Mainframe access obtained for SHARE Dallas 2022 Hackathon for IBM Z.