Added a bunch of stuff

This commit is contained in:
Win 2025-09-20 10:42:27 +07:00
parent 244b0a7eb7
commit 01bcdabd06
18 changed files with 1580 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,2 @@
gcc -o console_example console_example.c
gcc -o console_json -DJSON_SKIP_WHITESPACE console_json.c json.c

View File

@ -0,0 +1,65 @@
/* Example program showing how to invoke job_wizard
* from a simple console program in order to execute a task,
* then capture the output and print (without parsing).
*
* Created by Sally Goldin for SEN-210 on 15 September 2025
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
// Open the redirect file and display the contents
void displayOutput(char* redirectFilename)
{
FILE* pF = NULL;
char* textbuffer = NULL;
pF = fopen(redirectFilename,"r");
if (pF != NULL)
{
// get the size of the file
fseek(pF, 0L, SEEK_END);
int size = ftell(pF);
rewind(pF);
textbuffer = calloc(size + 2, sizeof(char)); // +2 for terminating 0
if (textbuffer == NULL)
{
printf("Error allocating space to store results\n");
return;
}
if (fread(textbuffer,sizeof(char),size,pF) != size)
{
printf("Error reading data from result file\n");
return;
}
printf("RESULTS\n");
printf(textbuffer);
free(textbuffer);
}
}
/* main program executes a search with no arguments */
int main(int argc, char* argv)
{
char* userEmail = "sally@cmkl.ac.th";
char* outputFile = "output.txt";
char jobwizardCmd[2048];
int returnCode;
// Create the command to execute
// In your real console-based UI, you probably want different functions
// that know about the arguments for different job_wizard commands
sprintf(jobwizardCmd,"./job_wizard -task search -email %s > %s 2>&1",userEmail,outputFile);
// note that 2>&1 redirects both standard output and standard error to the file output.txt
returnCode = system(jobwizardCmd);
if (returnCode != 0)
{
printf("Error %d executing job_wizard command\n");
printf("Command: |%s|\n",jobwizardCmd);
}
else
{
printf("Success!\n");
displayOutput(outputFile);
}
}

View File

@ -0,0 +1,201 @@
/* console_json.c
* Example program showing how to invoke job_wizard
* from a simple console program in order to execute a task,
* then capture the output and parse as JSON.
*
* Uses https://github.com/whyisitworking/C-Simple-JSON-Parser
*
* Created by Sally Goldin for SEN-210 on 15 September 2025
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "json.h"
// structure to hold one search result, a job summary
typedef struct
{
char job_id[8];
char title[64];
int is_open; // boolean
char date_posted[32];
} JOB_SUMMARY_T;
// Open the redirect file, reads and returns the content
// as a null terminated text string. Note that the returned
// string must be freed by the caller when no longer needed
char* readOutput(char* redirectFilename)
{
FILE* pF = NULL;
char* textbuffer = NULL;
pF = fopen(redirectFilename,"r");
if (pF != NULL)
{
// get the size of the file
fseek(pF, 0L, SEEK_END);
int size = ftell(pF);
rewind(pF);
textbuffer = calloc(size+2, sizeof(char)); // +2 for 0 term
if (textbuffer == NULL)
{
printf("Error allocating space to store results\n");
return NULL;
}
if (fread(textbuffer,sizeof(char),size,pF) != size)
{
printf("Error reading data from result file\n");
return NULL;
}
}
return (textbuffer);
}
/* parse the passed string and return the generic structure (json_element)
* build by C-Simple-JSON-Parser.
* Also returns a status via the integer pointer - 0 if okay, else -1
*/
typed(json_element) parseJsonString(char* rawJsonText, int* pStatus)
{
// based on example in the C-Simple-JSON-Parser repo
typed(json_element) element;
*pStatus = 0; // assume it will work
result(json_element) element_result = json_parse(rawJsonText);
if (result_is_err(json_element)(&element_result))
{
typed(json_error) error = result_unwrap_err(json_element)(&element_result);
fprintf(stderr, "Error parsing JSON: %s\n", json_error_to_string(error));
*pStatus = -1;
}
else
{
element = result_unwrap(json_element)(&element_result);
}
return element;
}
/* Attempts to parse the string passed as rawJsonText into
* an array of structures that represent job summaries.
* This is a two step process. The first, which parses the JSON,
* will be the same for all job_wizard results. The second extracts
* job summary information from the generic structures produced
* by the first.
* Returns 0 for success, -1 for error
* If successful, also allocates and returns an array of results.
* This array must be freed by the caller.
* Also sets the value of pJobCount
*/
int parseSearchResults(char* rawJsonText, JOB_SUMMARY_T** allResults,int *pJobCount)
{
int status = 0;
int i,j;
JOB_SUMMARY_T * resultArray = NULL;
typed(json_element) element = parseJsonString(rawJsonText,&status);
if (status < 0)
{
return status; // do we need to free the element?
}
// we expect an array of jobs
typed(json_array) *arr = element.value.as_array;
*pJobCount = arr->count;
printf("Found %d jobs\n",*pJobCount);
resultArray = (JOB_SUMMARY_T*) calloc(*pJobCount,sizeof(JOB_SUMMARY_T));
if (resultArray == NULL)
{
printf("Error allocating job summary structures\n");
status = -1;
return status;
}
*allResults = resultArray;
for (j=0; j < *pJobCount; j++)
{
typed(json_element) element = arr->elements[j];
typed(json_object) *obj = element.value.as_object;
for (i = 0; i < obj->count; i++)
{
typed(json_entry) entry = *(obj->entries[i]);
typed(json_string) key = entry.key;
typed(json_element_value) value = entry.element.value;
if (strcmp(key,"job_id") == 0)
{
strcpy(resultArray[j].job_id,value.as_string);
}
else if (strcmp(key,"title") == 0)
{
strcpy(resultArray[j].title,value.as_string);
}
else if (strcmp(key,"is_open") == 0)
{
if (value.as_boolean)
resultArray[j].is_open = 1;
else
resultArray[j].is_open = 0;
}
else if (strcmp(key,"date_posted") == 0)
{
strcpy(resultArray[j].date_posted,value.as_string);
}
else
{
printf("Unrecognized object key %s\n",key);
}
}
}
json_free(&element);
return status;
}
/* Display the contents of a job structure as a line of text
*/
void printJobSummary(JOB_SUMMARY_T job)
{
printf("%6s %32s %4s %12s\n",
job.job_id,job.title,job.is_open? "t" : "f", job.date_posted);
}
/* main program executes a search with no arguments */
int main(int argc, char* argv)
{
char* userEmail = "sally@cmkl.ac.th";
char* outputFile = "output.txt";
char jobwizardCmd[2048];
char* resultText = NULL; // holds results, must be freed after use
int returnCode;
int jobCount;
int j;
JOB_SUMMARY_T * searchResults = NULL; // array of structs allocated for parsed JSON
// Create the command to execute
// In your real console-based UI, you probably want different functions
// that know about the arguments for different job_wizard commands
sprintf(jobwizardCmd,"./job_wizard -task search -email %s > %s 2>&1",userEmail,outputFile);
// note that 2>&1 redirects both standard output and standard error to the file output.txt
returnCode = system(jobwizardCmd);
if (returnCode != 0)
{
printf("Error %d executing job_wizard command\n");
printf("Command: |%s|\n",jobwizardCmd);
}
else
{
printf("Successfully ran job_wizard!\n");
resultText = readOutput(outputFile);
if (resultText != NULL)
{
returnCode = parseSearchResults(resultText,&searchResults,&jobCount);
if (returnCode != 0)
printf("Error parsing JSON\n");
if (searchResults != NULL)
{
for (j = 0; j < jobCount; j++)
printJobSummary(searchResults[j]);
free(searchResults);
}
free(resultText);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
#pragma once
#include <stddef.h>
#ifndef __cplusplus
typedef unsigned int bool;
#define true (1)
#define false (0)
#endif
#define typed(name) name##_t
typedef const char *typed(json_string);
typedef bool typed(json_boolean);
typedef union json_number_value_u typed(json_number_value);
typedef signed long typed(json_number_long);
typedef double typed(json_number_double);
typedef struct json_number_s typed(json_number);
typedef union json_element_value_u typed(json_element_value);
typedef struct json_element_s typed(json_element);
typedef struct json_entry_s typed(json_entry);
typedef struct json_object_s typed(json_object);
typedef struct json_array_s typed(json_array);
#define result(name) name##_result_t
#define result_ok(name) name##_result_ok
#define result_err(name) name##_result_err
#define result_is_ok(name) name##_result_is_ok
#define result_is_err(name) name##_result_is_err
#define result_unwrap(name) name##_result_unwrap
#define result_unwrap_err(name) name##_result_unwrap_err
#define result_map_err(outer_name, inner_name, value) \
result_err(outer_name)(result_unwrap_err(inner_name)(value))
#define result_try(outer_name, inner_name, lvalue, rvalue) \
result(inner_name) lvalue##_result = rvalue; \
if (result_is_err(inner_name)(&lvalue##_result)) \
return result_map_err(outer_name, inner_name, &lvalue##_result); \
const typed(inner_name) lvalue = result_unwrap(inner_name)(&lvalue##_result);
#define declare_result_type(name) \
typedef struct name##_result_s { \
typed(json_boolean) is_ok; \
union { \
typed(name) value; \
typed(json_error) err; \
} inner; \
} result(name); \
result(name) result_ok(name)(typed(name)); \
result(name) result_err(name)(typed(json_error)); \
typed(json_boolean) result_is_ok(name)(result(name) *); \
typed(json_boolean) result_is_err(name)(result(name) *); \
typed(name) result_unwrap(name)(result(name) *); \
typed(json_error) result_unwrap_err(name)(result(name) *);
typedef enum json_element_type_e {
JSON_ELEMENT_TYPE_STRING = 0,
JSON_ELEMENT_TYPE_NUMBER,
JSON_ELEMENT_TYPE_OBJECT,
JSON_ELEMENT_TYPE_ARRAY,
JSON_ELEMENT_TYPE_BOOLEAN,
JSON_ELEMENT_TYPE_NULL
} typed(json_element_type);
typedef enum json_number_type_e {
JSON_NUMBER_TYPE_LONG = 0,
JSON_NUMBER_TYPE_DOUBLE,
} typed(json_number_type);
union json_number_value_u {
typed(json_number_long) as_long;
typed(json_number_double) as_double;
};
struct json_number_s {
typed(json_number_type) type;
typed(json_number_value) value;
};
union json_element_value_u {
typed(json_string) as_string;
typed(json_number) as_number;
typed(json_object) * as_object;
typed(json_array) * as_array;
typed(json_boolean) as_boolean;
};
struct json_element_s {
typed(json_element_type) type;
typed(json_element_value) value;
};
struct json_entry_s {
typed(json_string) key;
typed(json_element) element;
};
struct json_object_s {
typed(size) count;
typed(json_entry) * *entries;
};
struct json_array_s {
typed(size) count;
typed(json_element) * elements;
};
typedef enum json_error_e {
JSON_ERROR_EMPTY = 0,
JSON_ERROR_INVALID_TYPE,
JSON_ERROR_INVALID_KEY,
JSON_ERROR_INVALID_VALUE
} typed(json_error);
declare_result_type(json_element_type)
declare_result_type(json_element_value)
declare_result_type(json_element)
declare_result_type(json_entry)
declare_result_type(json_string)
declare_result_type(size)
/**
* @brief Parses a JSON string into a JSON element {json_element_t}
* with a fallible `result` type
*
* @param json_str The raw JSON string
* @return The parsed {json_element_t} wrapped in a `result` type
*/
result(json_element) json_parse(typed(json_string) json_str);
/**
* @brief Tries to get the element by key. If not found, returns
* a {JSON_ERROR_INVALID_KEY} error
*
* @param object The object to find the key in
* @param key The key of the element to be found
* @return Either a {json_element_t} or {json_error_t}
*/
result(json_element)
json_object_find(typed(json_object) * object, typed(json_string) key);
/**
* @brief Prints a JSON element {json_element_t} with proper
* indentation
*
* @param indent The number of spaces to indent each level by
*/
void json_print(typed(json_element) * element, int indent);
/**
* @brief Frees a JSON element {json_element_t} from memory
*
* @param element The JSON element {json_element_t} to free
*/
void json_free(typed(json_element) * element);
/**
* @brief Returns a string representation of JSON error {json_error_t} type
*
* @param error The JSON error enum {json_error_t} type
* @return The string representation
*/
typed(json_string) json_error_to_string(typed(json_error) error);

View File

@ -0,0 +1,2 @@
JOBWIZARD_API_PORT=8889
JOBWIZARD_DB_NAME=database/jobwizard_db

View File

@ -0,0 +1,12 @@
To import CSV files into SQLITE:
sqlite3 [dbname]
.mode csv
.import [file] [table]
NOTE that even though the ID columns in the job_wizard DB are flagged as
"autoincrement", SQLITE does not really support this. So we have to provide ID
values explicitly in the CSV files.
Above assumes no column headers in the file. I believe there is a way to tell
it to skip column headers.

View File

@ -0,0 +1,12 @@
1,sally@cmkl.ac.th,Front End Developer,Design and build attractive and highly usable UIs using React/JS,0,0,0,,1,2025-06-27 13:41 +700
2,sally@cmkl.ac.th,Back End Developer,Microservices; REST APIs; Go language; Database design and implementation,2,2,40000,,1,2025-06-27 13:45 +700
3,joe@cmkl.ac.th,HR Director,Manage onboarding - evaluation - staff retention - staff benefits for small university,3,5,95000,,1,2025-06-27 13:50 +700
4,mark@cmkl.ac.th,Executive Secretary,Handle day to day management tasks for university president,1,3,35000,,1,2025-07-02 13:50 +700
5,joe@cmkl.ac.th,Student Relations Officer,Assist students with planning study; gather feedback and complaints; interface with curriculum committee,2,3,42000,,1,2025-07-02 13:50 +700
6,sally@cmkl.ac.th,Professor,Teaching and research to support the university ,4,5,95000,,1,2025-07-02 13:50 +700
7,joe@cmkl.ac.th,Software Project Leader,Allocate tasks to software development team; monitor progress; train new developers; report to managment,3,4,50000,,1,2025-09-15 13:50 +700
8,joe@cmkl.ac.th,Graphics Professional,"Create graphics content including imagery, videos, slide decks; acquire photos at university events",3,2,32600,,1,2025-09-15 13:50 +700
9,joe@cmkl.ac.th,Janitor,Cleaning and maintenance,1,0,12500,lisa@outlook.com,0,2025-09-16 13:50 +700
10,joe@cmkl.ac.th,Driver,Part time - Drive university van on schedule rounds; occasionally chauffer university president,1,3,18500,,1,2025-09-16 13:50 +700
11,mark@cmkl.ac.th,CEO ,Top executive for promising tech start-up; compensation includes stock options,4,4,60000,,1,2025-09-17 13:50 +700
12,sally@cmkl.ac.th,UX Designer,Design user interfaces for in-house software; guide developers in implementation; handle usability tests,3,3,38000,jim@gmail.com,0,2025-09-17 13:45 +700
1 1 sally@cmkl.ac.th Front End Developer Design and build attractive and highly usable UIs using React/JS 0 0 0 1 2025-06-27 13:41 +700
2 2 sally@cmkl.ac.th Back End Developer Microservices; REST APIs; Go language; Database design and implementation 2 2 40000 1 2025-06-27 13:45 +700
3 3 joe@cmkl.ac.th HR Director Manage onboarding - evaluation - staff retention - staff benefits for small university 3 5 95000 1 2025-06-27 13:50 +700
4 4 mark@cmkl.ac.th Executive Secretary Handle day to day management tasks for university president 1 3 35000 1 2025-07-02 13:50 +700
5 5 joe@cmkl.ac.th Student Relations Officer Assist students with planning study; gather feedback and complaints; interface with curriculum committee 2 3 42000 1 2025-07-02 13:50 +700
6 6 sally@cmkl.ac.th Professor Teaching and research to support the university 4 5 95000 1 2025-07-02 13:50 +700
7 7 joe@cmkl.ac.th Software Project Leader Allocate tasks to software development team; monitor progress; train new developers; report to managment 3 4 50000 1 2025-09-15 13:50 +700
8 8 joe@cmkl.ac.th Graphics Professional Create graphics content including imagery, videos, slide decks; acquire photos at university events 3 2 32600 1 2025-09-15 13:50 +700
9 9 joe@cmkl.ac.th Janitor Cleaning and maintenance 1 0 12500 lisa@outlook.com 0 2025-09-16 13:50 +700
10 10 joe@cmkl.ac.th Driver Part time - Drive university van on schedule rounds; occasionally chauffer university president 1 3 18500 1 2025-09-16 13:50 +700
11 11 mark@cmkl.ac.th CEO Top executive for promising tech start-up; compensation includes stock options 4 4 60000 1 2025-09-17 13:50 +700
12 12 sally@cmkl.ac.th UX Designer Design user interfaces for in-house software; guide developers in implementation; handle usability tests 3 3 38000 jim@gmail.com 0 2025-09-17 13:45 +700

View File

@ -0,0 +1,5 @@
1,sally@cmkl.ac.th,Sally,Goldin,“0879990088”,5,2025-06-05
2,joe@cmkl.ac.th,Joe,Jenkins,“0329871233”,1,2025-06-22
3,mark@cmkl.ac.th,Mark,Masters,“0770992324”,3,2025-06-26
4,jim@gmail.com,James,Jamison,“0654329809”,2,2025-06-29
5,lisa@outlook.com,Lisa,Roberts,“0567876666”,1,2025-09-17
1 1 sally@cmkl.ac.th Sally Goldin “0879990088” 5 2025-06-05
2 2 joe@cmkl.ac.th Joe Jenkins “0329871233” 1 2025-06-22
3 3 mark@cmkl.ac.th Mark Masters “0770992324” 3 2025-06-26
4 4 jim@gmail.com James Jamison “0654329809” 2 2025-06-29
5 5 lisa@outlook.com Lisa Roberts “0567876666” 1 2025-09-17

View File

@ -0,0 +1,13 @@
# Lab 1: Introduction
Designing a user interface for the JobWizard CMD :D
**Looking at...**
- What the user will do
- How will they do it?
*Try to follow the Golden Rule of UIs*
## FUCK JAVA AND PYTHON. DISGUSTING.
## Reminder
Create account on Figma

View File

@ -0,0 +1 @@
# SEN-210 - Designing User Interface