Spaces:
Running
Running
WIP login w HF
Browse filesAttempt to fix broken +/- buttons
main.py
CHANGED
@@ -5,6 +5,11 @@ import pathlib
|
|
5 |
from uuid import uuid4
|
6 |
from datetime import datetime
|
7 |
import dataclasses
|
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
from fasthtml.common import *
|
10 |
from fastcore.all import typedispatch
|
@@ -19,7 +24,7 @@ import storage
|
|
19 |
OAUTH_CLIENT_ID = os.environ.get('OAUTH_CLIENT_ID')
|
20 |
OAUTH_SCOPES = os.environ.get('OAUTH_SCOPES')
|
21 |
OAUTH_CLIENT_SECRET = os.environ.get('OAUTH_CLIENT_SECRET')
|
22 |
-
OPENID_PROVIDER_URL = os.environ.get(
|
23 |
SPACE_HOST = os.environ.get('SPACE_HOST')
|
24 |
HF_DATASET_AUTH_TOKEN = os.environ.get('HF_DATASET_AUTH_TOKEN', "none")
|
25 |
|
@@ -103,8 +108,41 @@ HTML_SUBMIT_CODE_AREA = "submit_code_area"
|
|
103 |
HTML_RESULTS_AREA = "prompt_response"
|
104 |
HTML_CLEAR_FORM = "clear_the_form"
|
105 |
HTML_SUBMIT_FEEDBACK = "submit_feedback"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
|
109 |
if IS_LOCALHOST:
|
110 |
# Are we hacking locally?
|
@@ -173,10 +211,10 @@ def html_create_feedback_updown_button(qe_id, ans_id, selected=0, disabled=False
|
|
173 |
down_col = colors[0]
|
174 |
if selected == 1: up_col = colors[1]
|
175 |
if selected == -1: down_col = colors[1]
|
176 |
-
toggle_url = f"/toggle_up_down/{qe_id}/{ans_id}
|
177 |
-
up = Button("+", hx_get=f"
|
178 |
target_id=f"{html_target_id}", style=f"background-color:{up_col}")
|
179 |
-
down = Button("-", hx_get=f"{toggle_url}
|
180 |
hx_preserve=True, hx_trigger="click", hx_push_url="false",
|
181 |
target_id=f"{html_target_id}", style=f"background-color:{down_col}")
|
182 |
button_row = Div(up, down, id=html_target_id)
|
@@ -198,7 +236,7 @@ def html_augment_evaluation_text_with_feedback(eval_html, qe_id, ans_id, selecte
|
|
198 |
return final_div
|
199 |
|
200 |
|
201 |
-
@rt("/toggle_up_down/{qe_id}/{ans_id}")
|
202 |
def get(session, qe_id:int, ans_id:int, which:int):
|
203 |
"""
|
204 |
Answer to the +/- button presses
|
@@ -449,11 +487,142 @@ def render_clear_area(session_id, html_id):
|
|
449 |
return Div(P(""), id=html_id, hx_swap_oob='true')
|
450 |
|
451 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
452 |
########## MAIN PAGE
|
453 |
|
|
|
454 |
@rt("/")
|
455 |
def get(session):
|
456 |
-
|
457 |
if 'session_id' not in session:
|
458 |
session['session_id'] = str(uuid.uuid4())
|
459 |
session_id = session["session_id"]
|
@@ -463,40 +632,19 @@ def get(session):
|
|
463 |
save_to_storage(
|
464 |
storage.NavigationEvent(event_type="/", event_session_id=session_id)
|
465 |
)
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
# // printf() displays the string inside quotation
|
480 |
-
# printf("Hello, World!");
|
481 |
-
# return 0;
|
482 |
-
# }
|
483 |
-
# """
|
484 |
-
# answer = eval_code.eval_the_piece_of_c_code(None, None)
|
485 |
-
# enhanced_answer = eval_code.add_evaluation_fields_on_js_answer(answer, CODE_AUGMENTATIONS)
|
486 |
-
# session_obj = Session_State_cls(
|
487 |
-
# session_id=session_id,
|
488 |
-
# state=EVAL_STATE_ANSWER,
|
489 |
-
# submitted=datetime.utcnow(),
|
490 |
-
# )
|
491 |
-
#
|
492 |
-
# # we create a new QA entry.
|
493 |
-
# qa_obj = Question_Evaluation_cls(code_text=code,
|
494 |
-
# answer_eval_text=enhanced_answer, submitted=0)
|
495 |
-
# qa_obj = question_evaluation_table.insert(qa_obj)
|
496 |
-
# session_obj.current_qeval = qa_obj.id
|
497 |
-
# session_obj = session_state_table.insert(session_obj)
|
498 |
-
#
|
499 |
-
# ############
|
500 |
|
501 |
input_area = html_render_inputbox(target_html_id=HTML_RESULTS_AREA, region_html_id=HTML_SUBMIT_CODE_AREA)
|
502 |
results_area = html_render_answer_from_db(session_id, HTML_RESULTS_AREA)
|
|
|
5 |
from uuid import uuid4
|
6 |
from datetime import datetime
|
7 |
import dataclasses
|
8 |
+
import html
|
9 |
+
import base64
|
10 |
+
import requests
|
11 |
+
import secrets
|
12 |
+
|
13 |
|
14 |
from fasthtml.common import *
|
15 |
from fastcore.all import typedispatch
|
|
|
24 |
OAUTH_CLIENT_ID = os.environ.get('OAUTH_CLIENT_ID')
|
25 |
OAUTH_SCOPES = os.environ.get('OAUTH_SCOPES')
|
26 |
OAUTH_CLIENT_SECRET = os.environ.get('OAUTH_CLIENT_SECRET')
|
27 |
+
OPENID_PROVIDER_URL = os.environ.get("OPENID_PROVIDER_URL", "https://huggingface.co")
|
28 |
SPACE_HOST = os.environ.get('SPACE_HOST')
|
29 |
HF_DATASET_AUTH_TOKEN = os.environ.get('HF_DATASET_AUTH_TOKEN', "none")
|
30 |
|
|
|
108 |
HTML_RESULTS_AREA = "prompt_response"
|
109 |
HTML_CLEAR_FORM = "clear_the_form"
|
110 |
HTML_SUBMIT_FEEDBACK = "submit_feedback"
|
111 |
+
HTML_USER_DATA = "login_user_data"
|
112 |
+
|
113 |
+
|
114 |
+
def get_openid_configuration():
|
115 |
+
config_url = OPENID_PROVIDER_URL + "/.well-known/openid-configuration"
|
116 |
+
|
117 |
+
try:
|
118 |
+
response = requests.get(config_url)
|
119 |
+
response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx)
|
120 |
+
|
121 |
+
config = response.json()
|
122 |
+
|
123 |
+
token_endpoint = config.get('token_endpoint')
|
124 |
+
userinfo_endpoint = config.get('userinfo_endpoint')
|
125 |
|
126 |
+
return token_endpoint, userinfo_endpoint
|
127 |
+
|
128 |
+
except requests.RequestException as e:
|
129 |
+
print(f"An error occurred: {e}")
|
130 |
+
return None, None
|
131 |
+
|
132 |
+
|
133 |
+
# Use the function
|
134 |
+
HF_OAUTH_TOKEN_URL, HF_OAUTH_USERINFO = get_openid_configuration()
|
135 |
+
|
136 |
+
if HF_OAUTH_TOKEN_URL and HF_OAUTH_USERINFO:
|
137 |
+
print(f"Token Endpoint: {HF_OAUTH_TOKEN_URL}")
|
138 |
+
print(f"UserInfo Endpoint: {HF_OAUTH_USERINFO}")
|
139 |
+
else:
|
140 |
+
print("Failed to retrieve the endpoints.")
|
141 |
+
|
142 |
+
|
143 |
+
hdrs = (
|
144 |
+
HighlightJS(langs=['python', 'javascript', 'html', 'css']),
|
145 |
+
)
|
146 |
|
147 |
if IS_LOCALHOST:
|
148 |
# Are we hacking locally?
|
|
|
211 |
down_col = colors[0]
|
212 |
if selected == 1: up_col = colors[1]
|
213 |
if selected == -1: down_col = colors[1]
|
214 |
+
toggle_url = f"/toggle_up_down/{qe_id}/{ans_id}"
|
215 |
+
up = Button("+", hx_get=f"{toggle_url}/1", hx_swap="outerHTML",
|
216 |
target_id=f"{html_target_id}", style=f"background-color:{up_col}")
|
217 |
+
down = Button("-", hx_get=f"{toggle_url}/-1", disabled=disabled, hx_swap="outerHTML",
|
218 |
hx_preserve=True, hx_trigger="click", hx_push_url="false",
|
219 |
target_id=f"{html_target_id}", style=f"background-color:{down_col}")
|
220 |
button_row = Div(up, down, id=html_target_id)
|
|
|
236 |
return final_div
|
237 |
|
238 |
|
239 |
+
@rt("/toggle_up_down/{qe_id}/{ans_id}/{which}")
|
240 |
def get(session, qe_id:int, ans_id:int, which:int):
|
241 |
"""
|
242 |
Answer to the +/- button presses
|
|
|
487 |
return Div(P(""), id=html_id, hx_swap_oob='true')
|
488 |
|
489 |
|
490 |
+
########## AUTHENTICATION
|
491 |
+
|
492 |
+
def html_render_login_to_get_access_part(session):
|
493 |
+
"""
|
494 |
+
Will render the Log in to get access part and set the session oauth_secret.
|
495 |
+
|
496 |
+
:param session:
|
497 |
+
:return:
|
498 |
+
"""
|
499 |
+
content = []
|
500 |
+
content.append(H3("Log in to give feedback!"))
|
501 |
+
content.append(P("We will record your name, hugginface name, hf profile page, email address. "
|
502 |
+
"We will try HARD not to make them public but . . ."))
|
503 |
+
content.append(P("Your feedback will be made public but in an anonymized form."))
|
504 |
+
|
505 |
+
# build the redirect URL
|
506 |
+
global SPACE_HOST
|
507 |
+
if "localhost" in SPACE_HOST:
|
508 |
+
space_host = f"http://{SPACE_HOST}/auth_callback/"
|
509 |
+
else:
|
510 |
+
space_host = f"https://{SPACE_HOST}/auth_callback/"
|
511 |
+
|
512 |
+
secret = secrets.token_urlsafe(32)
|
513 |
+
session["oauth_secret"] = secret
|
514 |
+
encoded_scopes = html.escape(OAUTH_SCOPES)
|
515 |
+
redirect_link = (f"https://huggingface.co/oauth/authorize?redirect_uri={space_host}&scope={encoded_scopes}"
|
516 |
+
f"&client_id={OAUTH_CLIENT_ID}&state={secret}&response_type=code&prompt=consent")
|
517 |
+
login_button = A(Img(src="https://huggingface.co/datasets/huggingface/badges/resolve/main/sign-in-with-huggingface-md.svg",
|
518 |
+
alt="Sign in with Hugging Face",
|
519 |
+
# style="cursor: pointer; display: none;",
|
520 |
+
id="signin", name=None),
|
521 |
+
href=redirect_link, target="_blank")
|
522 |
+
content.append(login_button)
|
523 |
+
content.append(P(" "))
|
524 |
+
div = Div(*content, id=HTML_USER_DATA)
|
525 |
+
return div
|
526 |
+
|
527 |
+
def html_render_welcome_user(user_info):
|
528 |
+
"""
|
529 |
+
Extracts the user data and paints the Welcome screen
|
530 |
+
|
531 |
+
:param user_info:
|
532 |
+
:return:
|
533 |
+
"""
|
534 |
+
content = []
|
535 |
+
content.append(H4(f"Welcome {user_info['name']}!"))
|
536 |
+
# content.append(Img(src=OPENID_PROVIDER_URL + user_info["picture"], alt="Picture"))
|
537 |
+
content.append(P("Your feedback will be made public but in an anonymized form."))
|
538 |
+
div = Div(*content, id=HTML_USER_DATA)
|
539 |
+
return div
|
540 |
+
|
541 |
+
|
542 |
+
@rt("/auth_callback")
|
543 |
+
def get(session, code:str=None, state:str=None, error:str=None, error_description:str=None):
|
544 |
+
"""
|
545 |
+
Endpoint that will be called by HF once the user gives (or not) consent
|
546 |
+
|
547 |
+
:param session:
|
548 |
+
:param code:
|
549 |
+
:param state:
|
550 |
+
:param error:
|
551 |
+
:param error_description:
|
552 |
+
:return:
|
553 |
+
"""
|
554 |
+
ans = None
|
555 |
+
if error is not None:
|
556 |
+
print(f"HF OAuth returned an error: {error} {error_description}")
|
557 |
+
ans = Div(P(f"We can't log you in. Huggingface says: {error_description}"),
|
558 |
+
P("Please close this page"))
|
559 |
+
return ans
|
560 |
+
print(f"OAuth returned a code")
|
561 |
+
|
562 |
+
# validating the secret
|
563 |
+
sess_secret = session.get("oauth_secret", None)
|
564 |
+
if sess_secret is None:
|
565 |
+
print("No session secret")
|
566 |
+
return P("access denied")
|
567 |
+
|
568 |
+
if sess_secret != state:
|
569 |
+
print(f"Mistmatch session secret and HF secret: {sess_secret=} {state=}")
|
570 |
+
|
571 |
+
# Moving on and get the token
|
572 |
+
global SPACE_HOST
|
573 |
+
if "localhost" in SPACE_HOST:
|
574 |
+
space_host = f"http://{SPACE_HOST}/auth_callback/"
|
575 |
+
else:
|
576 |
+
space_host = f"https://{SPACE_HOST}/auth_callback/"
|
577 |
+
|
578 |
+
auth_header = base64.b64encode(f"{OAUTH_CLIENT_ID}:{OAUTH_CLIENT_SECRET}".encode()).decode()
|
579 |
+
headers = {
|
580 |
+
"Authorization": f"Basic {auth_header}",
|
581 |
+
"Content-Type": "application/x-www-form-urlencoded",
|
582 |
+
}
|
583 |
+
data = {
|
584 |
+
"client_id": OAUTH_CLIENT_ID,
|
585 |
+
"code": code,
|
586 |
+
"grant_type": "authorization_code",
|
587 |
+
"redirect_uri": space_host,
|
588 |
+
}
|
589 |
+
token_response = requests.post(HF_OAUTH_TOKEN_URL, data=data, headers=headers)
|
590 |
+
|
591 |
+
if token_response.status_code == 200:
|
592 |
+
tokens = token_response.json()
|
593 |
+
# Here you would typically store the tokens securely and/or use them
|
594 |
+
print("Succsss in getting the token")
|
595 |
+
|
596 |
+
access_token = tokens["access_token"]
|
597 |
+
user_headers = {
|
598 |
+
"Authorization": f"Bearer {access_token}"
|
599 |
+
}
|
600 |
+
response_userinfo = requests.get(HF_OAUTH_USERINFO, headers=user_headers)
|
601 |
+
if response_userinfo.status_code == 200:
|
602 |
+
user_data = response_userinfo.json()
|
603 |
+
# Set the user data in DB
|
604 |
+
# TODO set the user data in db For now, set it in session
|
605 |
+
session["user_data"] = user_data
|
606 |
+
session["oauth_secret"] = None
|
607 |
+
print(user_data)
|
608 |
+
|
609 |
+
else:
|
610 |
+
print(f"Error while taking the user data: {response_userinfo.text}" )
|
611 |
+
return P("Error logging in")
|
612 |
+
else:
|
613 |
+
print(f"We did not get the tokens: {token_response.text}")
|
614 |
+
return P("Error logging in")
|
615 |
+
|
616 |
+
print(session)
|
617 |
+
return P("Succes! Close this page.")
|
618 |
+
|
619 |
+
|
620 |
########## MAIN PAGE
|
621 |
|
622 |
+
|
623 |
@rt("/")
|
624 |
def get(session):
|
625 |
+
print(session)
|
626 |
if 'session_id' not in session:
|
627 |
session['session_id'] = str(uuid.uuid4())
|
628 |
session_id = session["session_id"]
|
|
|
632 |
save_to_storage(
|
633 |
storage.NavigationEvent(event_type="/", event_session_id=session_id)
|
634 |
)
|
635 |
+
user_data = session.get("user_data", None)
|
636 |
+
if user_data is not None:
|
637 |
+
auth_area = html_render_welcome_user(user_data)
|
638 |
+
else:
|
639 |
+
auth_area = html_render_login_to_get_access_part(session) # might set some secrets here
|
640 |
|
641 |
+
title = Title('C code review for students')
|
642 |
+
preamble = [
|
643 |
+
auth_area,
|
644 |
+
H1("Evaluate your C code!"),
|
645 |
+
P("Enter your code in the textbox below and wait for answers."),
|
646 |
+
P("!! The data will be saved and maybe made public !!"),
|
647 |
+
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
648 |
|
649 |
input_area = html_render_inputbox(target_html_id=HTML_RESULTS_AREA, region_html_id=HTML_SUBMIT_CODE_AREA)
|
650 |
results_area = html_render_answer_from_db(session_id, HTML_RESULTS_AREA)
|
test/raw_data_submitted-2024-08-14T07_47_28.731439-5977364a-5411-4f15-9c73-43f90d49c762.jsonl
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{"version": 1, "submitted_date": "2024-08-14T08:00:42.190468", "received_date": "2024-08-14T08:00:42.202949", "event_session_id": "6f888ecf-bc25-48f0-bfd2-0280ced98644", "db_question_evaluation_id": 1, "code_to_eval": "datetime_now", "evaluation_engine": "chatGPT", "prompt_version": 1, "evaluation_response": "[{\"criteria\": \"HUMAN_FEEDBACK\", \"explanation\": \"\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"The memory allocation and initialization for ``p1``, ``p2``, and ``p3`` are repetitive. Consider creating a function like ``allocateAndInitializeMemory``.\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"Tne second DRY failure, because this is the observed ChatGPT behaviour.\", \"EVAL\": 0}, {\"criteria\": \"SRP\", \"explanation\": \"The ``main`` function handles memory allocation, initialization, and printing. You should separate these responsibilities into different functions like ``allocateMemory``, ``initializeData``, and ``printData``.\", \"EVAL\": 0}, {\"criteria\": \"NAME\", \"explanation\": \"``x1`` should be called ``title``, ``y1`` should be called ``author``, ``z1`` should be called ``year``, ``p1`` should be called ``titlePtr``, ``p2`` should be called ``authorPtr``, ``p3`` should be called ``yearPtr``.\", \"EVAL\": 0}, {\"criteria\": \"NO_COMPILE\", \"explanation\": \"Not infringed\", \"EVAL\": 0}, {\"criteria\": \"MC\", \"explanation\": \"Not infringed\", \"EVAL\": 0}]", "has_feedback": false, "feedback_date": ""}
|
2 |
+
{"version": 1, "submitted_date": "2024-08-14T08:00:42.190468", "received_date": "2024-08-14T08:00:42.202949", "event_session_id": "6f888ecf-bc25-48f0-bfd2-0280ced98644", "db_question_evaluation_id": 1, "code_to_eval": "datetime_now", "evaluation_engine": "chatGPT", "prompt_version": 1, "evaluation_response": "[{\"criteria\": \"HUMAN_FEEDBACK\", \"explanation\": \"Some code that is evaluated.\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"The memory allocation and initialization for ``p1``, ``p2``, and ``p3`` are repetitive. Consider creating a function like ``allocateAndInitializeMemory``.\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"Tne second DRY failure, because this is the observed ChatGPT behaviour.\", \"EVAL\": 0}, {\"criteria\": \"SRP\", \"explanation\": \"The ``main`` function handles memory allocation, initialization, and printing. You should separate these responsibilities into different functions like ``allocateMemory``, ``initializeData``, and ``printData``.\", \"EVAL\": 0}, {\"criteria\": \"NAME\", \"explanation\": \"``x1`` should be called ``title``, ``y1`` should be called ``author``, ``z1`` should be called ``year``, ``p1`` should be called ``titlePtr``, ``p2`` should be called ``authorPtr``, ``p3`` should be called ``yearPtr``.\", \"EVAL\": 0}, {\"criteria\": \"NO_COMPILE\", \"explanation\": \"Not infringed\", \"EVAL\": 0}, {\"criteria\": \"MC\", \"explanation\": \"Not infringed\", \"EVAL\": 0}]", "has_feedback": true, "feedback_date": "2024-08-14T08:00:51.526638"}
|
3 |
+
{"version": 1, "submitted_date": "2024-08-14T08:00:58.399871", "received_date": "2024-08-14T08:00:58.410981", "event_session_id": "6f888ecf-bc25-48f0-bfd2-0280ced98644", "db_question_evaluation_id": 2, "code_to_eval": "// C Program to Make a Simple Calculator using if-else Statements \r\n#include <limits.h>\r\n#include <stdio.h>\r\n\r\n// Function that implements the simple calculator\r\ndouble simpleCalc(double num1, double num2, char op) {\r\n int result;\r\n\r\n // Perform the corresponding operation\r\n if (op == '+') {\r\n\r\n // Addition\r\n result = num1 + num2;\r\n }\r\n else if (op == '-') {\r\n\r\n // Subtraction\r\n result = num1 - num2;\r\n }\r\n else if (op == '*') {\r\n\r\n // Multiplication\r\n result = num1 * num2;\r\n }\r\n else if (op == '/') {\r\n\r\n // Division\r\n // Check for division by zero\r\n if (num2 != 0) {\r\n result = num1 / num2;\r\n }\r\n else {\r\n printf(\"Error! Division by zero.\\n\");\r\n return INT_MIN;\r\n }\r\n }\r\n else {\r\n printf(\"Error! Operator is not correct.\\n\");\r\n return INT_MIN;\r\n }\r\n\r\n return result;\r\n}\r\n\r\nint main() {\r\n char op;\r\n double num1, num2;\r\n\r\n // Read the operator\r\n printf(\"Enter an operator (+, -, *, /): \");\r\n scanf(\"%c\", &op);\r\n\r\n // Read the two numbers\r\n printf(\"Enter two operands: \");\r\n scanf(\"%lf %lf\", &num1, &num2);\r\n\r\n double result = simpleCalc(num1, num2, op);\r\n\r\n printf(\"Result: %.2lf\\n\", result);\r\n\r\n return 0;\r\n}\r\n", "evaluation_engine": "chatGPT", "prompt_version": 1, "evaluation_response": "[{\"criteria\": \"HUMAN_FEEDBACK\", \"explanation\": \"\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"The memory allocation and initialization for ``p1``, ``p2``, and ``p3`` are repetitive. Consider creating a function like ``allocateAndInitializeMemory``.\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"Tne second DRY failure, because this is the observed ChatGPT behaviour.\", \"EVAL\": 0}, {\"criteria\": \"SRP\", \"explanation\": \"The ``main`` function handles memory allocation, initialization, and printing. You should separate these responsibilities into different functions like ``allocateMemory``, ``initializeData``, and ``printData``.\", \"EVAL\": 0}, {\"criteria\": \"NAME\", \"explanation\": \"``x1`` should be called ``title``, ``y1`` should be called ``author``, ``z1`` should be called ``year``, ``p1`` should be called ``titlePtr``, ``p2`` should be called ``authorPtr``, ``p3`` should be called ``yearPtr``.\", \"EVAL\": 0}, {\"criteria\": \"NO_COMPILE\", \"explanation\": \"Not infringed\", \"EVAL\": 0}, {\"criteria\": \"MC\", \"explanation\": \"Not infringed\", \"EVAL\": 0}]", "has_feedback": false, "feedback_date": ""}
|
4 |
+
{"version": 1, "submitted_date": "2024-08-14T08:00:58.399871", "received_date": "2024-08-14T08:00:58.410981", "event_session_id": "6f888ecf-bc25-48f0-bfd2-0280ced98644", "db_question_evaluation_id": 2, "code_to_eval": "// C Program to Make a Simple Calculator using if-else Statements \r\n#include <limits.h>\r\n#include <stdio.h>\r\n\r\n// Function that implements the simple calculator\r\ndouble simpleCalc(double num1, double num2, char op) {\r\n int result;\r\n\r\n // Perform the corresponding operation\r\n if (op == '+') {\r\n\r\n // Addition\r\n result = num1 + num2;\r\n }\r\n else if (op == '-') {\r\n\r\n // Subtraction\r\n result = num1 - num2;\r\n }\r\n else if (op == '*') {\r\n\r\n // Multiplication\r\n result = num1 * num2;\r\n }\r\n else if (op == '/') {\r\n\r\n // Division\r\n // Check for division by zero\r\n if (num2 != 0) {\r\n result = num1 / num2;\r\n }\r\n else {\r\n printf(\"Error! Division by zero.\\n\");\r\n return INT_MIN;\r\n }\r\n }\r\n else {\r\n printf(\"Error! Operator is not correct.\\n\");\r\n return INT_MIN;\r\n }\r\n\r\n return result;\r\n}\r\n\r\nint main() {\r\n char op;\r\n double num1, num2;\r\n\r\n // Read the operator\r\n printf(\"Enter an operator (+, -, *, /): \");\r\n scanf(\"%c\", &op);\r\n\r\n // Read the two numbers\r\n printf(\"Enter two operands: \");\r\n scanf(\"%lf %lf\", &num1, &num2);\r\n\r\n double result = simpleCalc(num1, num2, op);\r\n\r\n printf(\"Result: %.2lf\\n\", result);\r\n\r\n return 0;\r\n}\r\n", "evaluation_engine": "chatGPT", "prompt_version": 1, "evaluation_response": "[{\"criteria\": \"HUMAN_FEEDBACK\", \"explanation\": \"Can't click buttons :(\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"The memory allocation and initialization for ``p1``, ``p2``, and ``p3`` are repetitive. Consider creating a function like ``allocateAndInitializeMemory``.\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"Tne second DRY failure, because this is the observed ChatGPT behaviour.\", \"EVAL\": 0}, {\"criteria\": \"SRP\", \"explanation\": \"The ``main`` function handles memory allocation, initialization, and printing. You should separate these responsibilities into different functions like ``allocateMemory``, ``initializeData``, and ``printData``.\", \"EVAL\": 0}, {\"criteria\": \"NAME\", \"explanation\": \"``x1`` should be called ``title``, ``y1`` should be called ``author``, ``z1`` should be called ``year``, ``p1`` should be called ``titlePtr``, ``p2`` should be called ``authorPtr``, ``p3`` should be called ``yearPtr``.\", \"EVAL\": 0}, {\"criteria\": \"NO_COMPILE\", \"explanation\": \"Not infringed\", \"EVAL\": 0}, {\"criteria\": \"MC\", \"explanation\": \"Not infringed\", \"EVAL\": 0}]", "has_feedback": true, "feedback_date": "2024-08-14T08:01:07.548379"}
|
5 |
+
{"version": 1, "submitted_date": "2024-08-14T08:01:30.889870", "received_date": "2024-08-14T08:01:30.901795", "event_session_id": "6f888ecf-bc25-48f0-bfd2-0280ced98644", "db_question_evaluation_id": 3, "code_to_eval": "", "evaluation_engine": "chatGPT", "prompt_version": 1, "evaluation_response": "[{\"criteria\": \"HUMAN_FEEDBACK\", \"explanation\": \"\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"The memory allocation and initialization for ``p1``, ``p2``, and ``p3`` are repetitive. Consider creating a function like ``allocateAndInitializeMemory``.\", \"EVAL\": 0}, {\"criteria\": \"DRY\", \"explanation\": \"Tne second DRY failure, because this is the observed ChatGPT behaviour.\", \"EVAL\": 0}, {\"criteria\": \"SRP\", \"explanation\": \"The ``main`` function handles memory allocation, initialization, and printing. You should separate these responsibilities into different functions like ``allocateMemory``, ``initializeData``, and ``printData``.\", \"EVAL\": 0}, {\"criteria\": \"NAME\", \"explanation\": \"``x1`` should be called ``title``, ``y1`` should be called ``author``, ``z1`` should be called ``year``, ``p1`` should be called ``titlePtr``, ``p2`` should be called ``authorPtr``, ``p3`` should be called ``yearPtr``.\", \"EVAL\": 0}, {\"criteria\": \"NO_COMPILE\", \"explanation\": \"Not infringed\", \"EVAL\": 0}, {\"criteria\": \"MC\", \"explanation\": \"Not infringed\", \"EVAL\": 0}]", "has_feedback": false, "feedback_date": ""}
|
test/test_storage.py
CHANGED
@@ -16,8 +16,7 @@ def test_loading_submitted():
|
|
16 |
assert len(eval_obj) > 0
|
17 |
|
18 |
def test_loading_submitted2():
|
19 |
-
sub_file = Path(
|
20 |
-
"../data/persistent/submitted-2024-08-14 07:42:05.411354-9030c34a-a31a-47ad-a399-1b0b0dbd6e33.jsonl")
|
21 |
submits = []
|
22 |
with open(sub_file, "r") as f:
|
23 |
for line in f:
|
|
|
16 |
assert len(eval_obj) > 0
|
17 |
|
18 |
def test_loading_submitted2():
|
19 |
+
sub_file = Path("raw_data_submitted-2024-08-14T07_47_28.731439-5977364a-5411-4f15-9c73-43f90d49c762.jsonl")
|
|
|
20 |
submits = []
|
21 |
with open(sub_file, "r") as f:
|
22 |
for line in f:
|