Skip to content

Commit 313e30f

Browse files
Merge pull request #33 from snelusha/chore/update-examples
Add new examples and refactor response aggregator
2 parents b4eb454 + ce6bb9f commit 313e30f

11 files changed

Lines changed: 323 additions & 52 deletions

File tree

apps/web/src/assets/examples.json

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,73 @@
88
"name": "examples",
99
"children": [
1010
{
11-
"kind": "file",
12-
"name": "01-orders.bal",
13-
"content": "import ballerina/io;\n\n// Shows pending orders with delivery fees\ntype Order record {|\n string id;\n string customer;\n int amount;\n string zone;\n|};\n\npublic function main() {\n Order[] orders = [\n {id: \"ORD001\", customer: \"Alice\", amount: 150, zone: \"Downtown\"},\n {id: \"ORD002\", customer: \"Bob\", amount: 75, zone: \"Suburb\"},\n {id: \"ORD003\", customer: \"Carol\", amount: 200, zone: \"Downtown\"}\n ];\n map\u003cint\u003e deliveryFee = {\"Downtown\": 5, \"Suburb\": 10};\n\n io:println(\"=== Pending Orders ===\");\n foreach int i in 0 ..\u003c orders.length() {\n Order ord = orders[i];\n io:println(i + 1, \". \", ord.id, \" | \",\n ord.customer, \" | $\", ord.amount,\n \" | \", ord.zone, \" (fee: $\", deliveryFee[ord.zone], \")\");\n }\n}\n\n"
11+
"kind": "dir",
12+
"name": "01-response-aggregator",
13+
"children": [
14+
{
15+
"kind": "dir",
16+
"name": "modules",
17+
"children": [
18+
{
19+
"kind": "dir",
20+
"name": "handler",
21+
"children": [
22+
{
23+
"kind": "file",
24+
"name": "handler.bal",
25+
"content": "import ballerina/io;\n\nimport playground/response_aggregator.types;\n\n// Response flags\npublic const int CACHED = 1 \u003c\u003c 0;\npublic const int PARTIAL = 1 \u003c\u003c 1;\npublic const int PAGINATED = 1 \u003c\u003c 2;\n\n// Processes and displays an API response with its flags and result.\npublic function processResponse(types:ApiResponse res) {\n io:println(\"\\nEndpoint: \", res.ep, \",\\n Status: \", res.status);\n\n if res.flags \u003e= PAGINATED {\n io:println(\" [Paginated]\");\n } else if res.flags == CACHED {\n io:println(\" [Cached]\");\n } else {\n io:println(\" [Partial]\");\n }\n\n any result = res.result;\n if result is int {\n int count = \u003cint\u003eresult;\n io:println(\" Count: \", count);\n } else if result is string {\n io:println(\" Info: \", result);\n }\n}\n\n"
26+
}
27+
]
28+
},
29+
{
30+
"kind": "dir",
31+
"name": "types",
32+
"children": [
33+
{
34+
"kind": "file",
35+
"name": "types.bal",
36+
"content": "// API response record type definition.\npublic type ApiResponse record {|\n string ep;\n int status;\n int flags;\n any result;\n|};\n\n"
37+
}
38+
]
39+
}
40+
]
41+
},
42+
{
43+
"kind": "file",
44+
"name": "Ballerina.toml",
45+
"content": "[package]\norg = \"playground\"\nname = \"response_aggregator\"\nversion = \"0.1.0\"\n"
46+
},
47+
{
48+
"kind": "file",
49+
"name": "main.bal",
50+
"content": "import response_aggregator.handler;\nimport response_aggregator.types;\n\nimport ballerina/io;\n\npublic function main() {\n types:ApiResponse[] responses = [\n {ep: \"/users\", status: 200, flags: handler:CACHED, result: 150},\n {ep: \"/orders\", status: 200, flags: handler:CACHED + handler:PAGINATED, result: \"paginated\"},\n {ep: \"/products\", status: 206, flags: handler:PARTIAL, result: 42}\n ];\n [string, int] healthCheck = [\"/health\", 200];\n\n io:println(\"Health Check: \", healthCheck[0], \" (\", healthCheck[1], \")\");\n\n foreach types:ApiResponse res in responses {\n handler:processResponse(res);\n }\n}\n\n"
51+
}
52+
]
1453
},
1554
{
1655
"kind": "file",
17-
"name": "02-response-aggregator.bal",
18-
"content": "import ballerina/io;\n\n// Aggregates responses from multiple API endpoints, categorizes them by status\n// and flags, and processes mixed result types.\ntype ApiResponse record {|\n string ep;\n int status;\n int flags;\n any result;\n|};\n\npublic function main() {\n // Response flags\n int cached = 1 \u003c\u003c 0;\n int partial = 1 \u003c\u003c 1;\n int paginated = 1 \u003c\u003c 2;\n\n ApiResponse[] responses = [\n {ep: \"/users\", status: 200, flags: cached, result: 150},\n {ep: \"/orders\", status: 200, flags: cached + paginated, result: \"paginated\"},\n {ep: \"/products\", status: 206, flags: partial, result: 42}\n ];\n [string, int] healthCheck = [\"/health\", 200];\n\n io:println(\"Health Check: \", healthCheck[0], \" (\", healthCheck[1], \")\");\n\n foreach ApiResponse res in responses {\n io:println(\"\\nEndpoint: \", res.ep, \",\\n Status: \", res.status);\n\n if res.flags \u003e= paginated {\n io:println(\" [Paginated]\");\n } else if res.flags == cached {\n io:println(\" [Cached]\");\n } else {\n io:println(\" [Partial]\");\n }\n\n any result = res.result;\n if result is int {\n int count = \u003cint\u003eresult;\n io:println(\" Count: \", count);\n } else if result is string {\n io:println(\" Info: \", result);\n }\n }\n}\n"
56+
"name": "02-orders.bal",
57+
"content": "import ballerina/io;\n\n// Shows pending orders with delivery fees\ntype Order record {|\n string id;\n string customer;\n int amount;\n string zone;\n|};\n\npublic function main() {\n Order[] orders = [\n {id: \"ORD001\", customer: \"Alice\", amount: 150, zone: \"Downtown\"},\n {id: \"ORD002\", customer: \"Bob\", amount: 75, zone: \"Suburb\"},\n {id: \"ORD003\", customer: \"Carol\", amount: 200, zone: \"Downtown\"}\n ];\n map\u003cint\u003e deliveryFee = {\"Downtown\": 5, \"Suburb\": 10};\n\n io:println(\"=== Pending Orders ===\");\n foreach int i in 0 ..\u003c orders.length() {\n Order ord = orders[i];\n io:println(i + 1, \". \", ord.id, \" | \",\n ord.customer, \" | $\", ord.amount,\n \" | \", ord.zone, \" (fee: $\", deliveryFee[ord.zone], \")\");\n }\n}\n\n"
1958
},
2059
{
2160
"kind": "file",
2261
"name": "03-fibonacci.bal",
2362
"content": "import ballerina/io;\n\npublic function main() {\n int n = 10;\n int i = 0;\n while (i \u003c n) {\n io:println(\"F(\", i, \") = \", fibonacci(i));\n i += 1;\n }\n}\n\nfunction fibonacci(int n) returns int {\n if (n \u003c= 1) {\n return n;\n }\n int prev = 0;\n int curr = 1;\n int i = 2;\n while (i \u003c= n) {\n int next = prev + curr;\n prev = curr;\n curr = next;\n i += 1;\n }\n return curr;\n}\n"
63+
},
64+
{
65+
"kind": "file",
66+
"name": "04-temperature-converter.bal",
67+
"content": "import ballerina/io;\n\nfunction validateFahrenheit(int f) returns int|error {\n if f \u003c -459 {\n return error(\"invalid fahrenheit: below absolute zero\");\n }\n return f;\n}\n\nfunction toCelsius(int f) returns int|error {\n int valid = check validateFahrenheit(f);\n return ((valid - 32) * 5) / 9;\n}\n\nfunction averageCelsius(int f1, int f2) returns int|error {\n int c1 = check toCelsius(f1);\n int c2 = check toCelsius(f2);\n return (c1 + c2) / 2;\n}\n\nfunction externalCalibrator(int c) returns int {\n // Simulate a dependency that may panic for suspicious values.\n if c \u003e 100 {\n panic error(\"calibrator overflow\");\n }\n return c + 1;\n}\n\nfunction safeConvertedValue(int f) returns int|error {\n int c = check toCelsius(f);\n var calibrated = trap externalCalibrator(c);\n if calibrated is error {\n return calibrated;\n }\n return calibrated;\n}\n\nfunction leaf(int f1, int f2) {\n _ = checkpanic averageCelsius(f1, f2);\n}\n\nfunction middle(int f1, int f2) {\n leaf(f1, f2);\n}\n\nfunction top(int f1, int f2) {\n middle(f1, f2);\n}\n\npublic function main() {\n io:println(\"=== Temperature Converter ===\");\n io:println(\"Safe Convert | Input: 98F\");\n io:println(\"Result | \", safeConvertedValue(98));\n io:println(\"\\nSafe Convert | Input: -500F\");\n io:println(\"Result | \", safeConvertedValue(-500));\n io:println(\"\\nAverage | Inputs: 98F, 32F\");\n io:println(\"Result | \", averageCelsius(98, 32));\n io:println(\"\\nStack Trace | top(-500, 32)\");\n\n top(-500, 32);\n}\n\n"
68+
},
69+
{
70+
"kind": "file",
71+
"name": "05-student-grades.bal",
72+
"content": "import ballerina/io;\n\ntype Student record {|\n int id;\n string name;\n int grade;\n|};\n\nfunction findById(Student[] students, int studentId) returns Student|error {\n Student[] rows = from var s in students\n where s.id == studentId\n select s;\n\n if rows.length() == 0 {\n return error(\"student not found\");\n }\n\n return rows[0];\n}\n\nfunction maxGrade(Student[] students) returns int {\n int best = students[0].grade;\n foreach Student s in students {\n if s.grade \u003e best {\n best = s.grade;\n }\n }\n return best;\n}\n\nfunction averageGrade(Student[] students) returns int {\n int sum = 0;\n foreach Student s in students {\n sum += s.grade;\n }\n return sum / students.length();\n}\n\nfunction topStudents(Student[] students) returns Student[] {\n int best = maxGrade(students);\n Student[] rows = from var s in students\n where s.grade == best\n select s;\n return rows;\n}\n\npublic function main() {\n Student[] students = [\n {id: 101, name: \"Asha\", grade: 78},\n {id: 102, name: \"Nimal\", grade: 92},\n {id: 103, name: \"Ravi\", grade: 85},\n {id: 104, name: \"Sara\", grade: 92}\n ];\n\n io:println(\"=== Student Grades ===\");\n io:println(\"Average Grade | \", averageGrade(students));\n io:println(\"\\nTop Students\");\n Student[] tops = topStudents(students);\n foreach Student s in tops {\n io:println(\"- \", s.id, \" | \", s.name, \" | \", s.grade);\n }\n\n io:println(\"\\nLookup | ID 102\");\n var row1 = findById(students, 102);\n if row1 is Student {\n io:println(\"Found | \", row1.id, \" | \", row1.name, \" | \", row1.grade);\n } else {\n io:println(\"Error | \", row1);\n }\n\n io:println(\"\\nLookup | ID 999\");\n var row2 = findById(students, 999);\n if row2 is Student {\n io:println(\"Found | \", row2.id, \" | \", row2.name, \" | \", row2.grade);\n } else {\n io:println(\"Error | \", row2);\n }\n}\n\n"
73+
},
74+
{
75+
"kind": "file",
76+
"name": "06-library-checkout.bal",
77+
"content": "import ballerina/io;\n\ntype LibraryItem object {\n function title() returns string;\n function author() returns string;\n function borrowBook() returns string;\n function returnBook() returns string;\n};\n\nclass Book {\n *LibraryItem;\n string name;\n string writer;\n boolean borrowed = false;\n\n function init(string name, string writer) {\n self.name = name;\n self.writer = writer;\n }\n\n function title() returns string {\n return self.name;\n }\n\n function author() returns string {\n return self.writer;\n }\n\n function borrowBook() returns string {\n if self.borrowed {\n return \"Sorry, \" + self.name + \" is already borrowed.\";\n }\n self.borrowed = true;\n return \"You borrowed \" + self.name + \".\";\n }\n\n function returnBook() returns string {\n if !self.borrowed {\n return \"This book was not borrowed.\";\n }\n self.borrowed = false;\n return \"You returned \" + self.name + \".\";\n }\n}\n\npublic function main() {\n LibraryItem book1 = new Book(\"The Hobbit\", \"J.R.R. Tolkien\");\n LibraryItem book2 = new Book(\"Harry Potter and the Philosopher’s Stone\", \"J.K. Rowling\");\n\n io:println(\"=== Library Checkout ===\");\n io:println(\"Book 1 | \", book1.title(), \" | \", book1.author());\n io:println(\"Book 2 | \", book2.title(), \" | \", book2.author());\n\n io:println(\"\\nBorrow #1 | \", book1.borrowBook());\n io:println(\"Borrow #2 | \", book1.borrowBook());\n\n io:println(\"\\nReturn #1 | \", book1.returnBook());\n io:println(\"Return #2 | \", book1.returnBook());\n}\n\n"
2478
}
2579
]
2680
}

apps/web/src/components/file-route-sync.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212

1313
import { useShare } from "@/hooks/use-share";
1414

15-
const DEFAULT_FILE = "/tmp/examples/01-orders.bal";
15+
const DEFAULT_FILE = "/tmp/examples/01-response-aggregator/main.bal";
1616
const DEFAULT_SPLAT = DEFAULT_FILE.replace(/^\/+/, "");
1717

1818
function normalizeSplat(splat: string | undefined): string | null {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[package]
2+
org = "playground"
3+
name = "response_aggregator"
4+
version = "0.1.0"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import response_aggregator.handler;
2+
import response_aggregator.types;
3+
4+
import ballerina/io;
5+
6+
public function main() {
7+
types:ApiResponse[] responses = [
8+
{ep: "/users", status: 200, flags: handler:CACHED, result: 150},
9+
{ep: "/orders", status: 200, flags: handler:CACHED + handler:PAGINATED, result: "paginated"},
10+
{ep: "/products", status: 206, flags: handler:PARTIAL, result: 42}
11+
];
12+
[string, int] healthCheck = ["/health", 200];
13+
14+
io:println("Health Check: ", healthCheck[0], " (", healthCheck[1], ")");
15+
16+
foreach types:ApiResponse res in responses {
17+
handler:processResponse(res);
18+
}
19+
}
20+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import ballerina/io;
2+
3+
import playground/response_aggregator.types;
4+
5+
// Response flags
6+
public const int CACHED = 1 << 0;
7+
public const int PARTIAL = 1 << 1;
8+
public const int PAGINATED = 1 << 2;
9+
10+
// Processes and displays an API response with its flags and result.
11+
public function processResponse(types:ApiResponse res) {
12+
io:println("\nEndpoint: ", res.ep, ",\n Status: ", res.status);
13+
14+
if res.flags >= PAGINATED {
15+
io:println(" [Paginated]");
16+
} else if res.flags == CACHED {
17+
io:println(" [Cached]");
18+
} else {
19+
io:println(" [Partial]");
20+
}
21+
22+
any result = res.result;
23+
if result is int {
24+
int count = <int>result;
25+
io:println(" Count: ", count);
26+
} else if result is string {
27+
io:println(" Info: ", result);
28+
}
29+
}
30+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// API response record type definition.
2+
public type ApiResponse record {|
3+
string ep;
4+
int status;
5+
int flags;
6+
any result;
7+
|};
8+

examples/02-response-aggregator.bal

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import ballerina/io;
2+
3+
function validateFahrenheit(int f) returns int|error {
4+
if f < -459 {
5+
return error("invalid fahrenheit: below absolute zero");
6+
}
7+
return f;
8+
}
9+
10+
function toCelsius(int f) returns int|error {
11+
int valid = check validateFahrenheit(f);
12+
return ((valid - 32) * 5) / 9;
13+
}
14+
15+
function averageCelsius(int f1, int f2) returns int|error {
16+
int c1 = check toCelsius(f1);
17+
int c2 = check toCelsius(f2);
18+
return (c1 + c2) / 2;
19+
}
20+
21+
function externalCalibrator(int c) returns int {
22+
// Simulate a dependency that may panic for suspicious values.
23+
if c > 100 {
24+
panic error("calibrator overflow");
25+
}
26+
return c + 1;
27+
}
28+
29+
function safeConvertedValue(int f) returns int|error {
30+
int c = check toCelsius(f);
31+
var calibrated = trap externalCalibrator(c);
32+
if calibrated is error {
33+
return calibrated;
34+
}
35+
return calibrated;
36+
}
37+
38+
function leaf(int f1, int f2) {
39+
_ = checkpanic averageCelsius(f1, f2);
40+
}
41+
42+
function middle(int f1, int f2) {
43+
leaf(f1, f2);
44+
}
45+
46+
function top(int f1, int f2) {
47+
middle(f1, f2);
48+
}
49+
50+
public function main() {
51+
io:println("=== Temperature Converter ===");
52+
io:println("Safe Convert | Input: 98F");
53+
io:println("Result | ", safeConvertedValue(98));
54+
io:println("\nSafe Convert | Input: -500F");
55+
io:println("Result | ", safeConvertedValue(-500));
56+
io:println("\nAverage | Inputs: 98F, 32F");
57+
io:println("Result | ", averageCelsius(98, 32));
58+
io:println("\nStack Trace | top(-500, 32)");
59+
60+
top(-500, 32);
61+
}
62+

examples/05-student-grades.bal

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import ballerina/io;
2+
3+
type Student record {|
4+
int id;
5+
string name;
6+
int grade;
7+
|};
8+
9+
function findById(Student[] students, int studentId) returns Student|error {
10+
Student[] rows = from var s in students
11+
where s.id == studentId
12+
select s;
13+
14+
if rows.length() == 0 {
15+
return error("student not found");
16+
}
17+
18+
return rows[0];
19+
}
20+
21+
function maxGrade(Student[] students) returns int {
22+
int best = students[0].grade;
23+
foreach Student s in students {
24+
if s.grade > best {
25+
best = s.grade;
26+
}
27+
}
28+
return best;
29+
}
30+
31+
function averageGrade(Student[] students) returns int {
32+
int sum = 0;
33+
foreach Student s in students {
34+
sum += s.grade;
35+
}
36+
return sum / students.length();
37+
}
38+
39+
function topStudents(Student[] students) returns Student[] {
40+
int best = maxGrade(students);
41+
Student[] rows = from var s in students
42+
where s.grade == best
43+
select s;
44+
return rows;
45+
}
46+
47+
public function main() {
48+
Student[] students = [
49+
{id: 101, name: "Asha", grade: 78},
50+
{id: 102, name: "Nimal", grade: 92},
51+
{id: 103, name: "Ravi", grade: 85},
52+
{id: 104, name: "Sara", grade: 92}
53+
];
54+
55+
io:println("=== Student Grades ===");
56+
io:println("Average Grade | ", averageGrade(students));
57+
io:println("\nTop Students");
58+
Student[] tops = topStudents(students);
59+
foreach Student s in tops {
60+
io:println("- ", s.id, " | ", s.name, " | ", s.grade);
61+
}
62+
63+
io:println("\nLookup | ID 102");
64+
var row1 = findById(students, 102);
65+
if row1 is Student {
66+
io:println("Found | ", row1.id, " | ", row1.name, " | ", row1.grade);
67+
} else {
68+
io:println("Error | ", row1);
69+
}
70+
71+
io:println("\nLookup | ID 999");
72+
var row2 = findById(students, 999);
73+
if row2 is Student {
74+
io:println("Found | ", row2.id, " | ", row2.name, " | ", row2.grade);
75+
} else {
76+
io:println("Error | ", row2);
77+
}
78+
}
79+

0 commit comments

Comments
 (0)