Spaces:
Sleeping
Sleeping
Tabrejmlkhan
commited on
Commit
β’
e24c25f
1
Parent(s):
e271a97
Upload 7 files
Browse files- Procfile +1 -0
- app.py +133 -0
- requirements.txt +6 -0
- templates/addcourse.html +29 -0
- templates/addprogram.html +18 -0
- templates/index.html +289 -0
- templates/result.html +46 -0
Procfile
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
web: gunicorn app:app
|
app.py
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
ο»Ώfrom flask import Flask, request, render_template, redirect, url_for
|
2 |
+
from transformers import AutoTokenizer, AutoModel
|
3 |
+
import torch
|
4 |
+
import os
|
5 |
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
6 |
+
app = Flask(__name__)
|
7 |
+
|
8 |
+
# Dictionary to store programs and their courses
|
9 |
+
programs = {}
|
10 |
+
|
11 |
+
# Default model name
|
12 |
+
current_model_name = 'sentence-transformers/all-mpnet-base-v2'
|
13 |
+
|
14 |
+
# Function to load the tokenizer and model dynamically
|
15 |
+
def load_model_and_tokenizer(model_name):
|
16 |
+
try:
|
17 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
18 |
+
model = AutoModel.from_pretrained(model_name)
|
19 |
+
return tokenizer, model, None
|
20 |
+
except Exception as e:
|
21 |
+
return None, None, str(e)
|
22 |
+
|
23 |
+
# Load the initial model and tokenizer
|
24 |
+
tokenizer, model, error = load_model_and_tokenizer(current_model_name)
|
25 |
+
|
26 |
+
def mean_pooling(token_embeddings, mask):
|
27 |
+
"""Applies mean pooling to token embeddings, considering the mask."""
|
28 |
+
mask = mask.unsqueeze(-1).expand(token_embeddings.size())
|
29 |
+
sum_embeddings = torch.sum(token_embeddings * mask, dim=1)
|
30 |
+
sum_mask = torch.clamp(mask.sum(dim=1), min=1e-9) # Avoid division by zero
|
31 |
+
return sum_embeddings / sum_mask
|
32 |
+
|
33 |
+
def compute_plo_embeddings():
|
34 |
+
"""Computes embeddings for the predefined PLOs."""
|
35 |
+
tokens = tokenizer(plos, padding=True, truncation=True, return_tensors='pt')
|
36 |
+
mask = tokens['attention_mask']
|
37 |
+
with torch.no_grad():
|
38 |
+
outputs = model(**tokens)
|
39 |
+
return mean_pooling(outputs.last_hidden_state, mask)
|
40 |
+
|
41 |
+
# Predefined Program Learning Outcomes (PLOs)
|
42 |
+
plos = [
|
43 |
+
"Analyze a complex computing problem and apply principles of computing and other relevant disciplines to identify solutions.",
|
44 |
+
"Design, implement, and evaluate a computing-based solution to meet a given set of computing requirements.",
|
45 |
+
"Communicate effectively in a variety of professional contexts.",
|
46 |
+
"Recognize professional responsibilities and make informed judgments in computing practice based on legal and ethical principles.",
|
47 |
+
"Function effectively as a member or leader of a team engaged in activities appropriate to the programβs discipline.",
|
48 |
+
"Support the delivery, use, and management of information systems within an information systems environment."
|
49 |
+
]
|
50 |
+
|
51 |
+
# Compute PLO embeddings (once at startup)
|
52 |
+
plo_embeddings = compute_plo_embeddings()
|
53 |
+
|
54 |
+
def get_similarity(input_sentence):
|
55 |
+
"""Calculates the similarity between an input sentence and predefined PLOs."""
|
56 |
+
tokens = tokenizer(input_sentence, padding=True, truncation=True, return_tensors='pt')
|
57 |
+
mask = tokens['attention_mask']
|
58 |
+
|
59 |
+
with torch.no_grad():
|
60 |
+
outputs = model(**tokens)
|
61 |
+
input_embedding = mean_pooling(outputs.last_hidden_state, mask)
|
62 |
+
|
63 |
+
similarities = torch.nn.functional.cosine_similarity(input_embedding, plo_embeddings)
|
64 |
+
return similarities
|
65 |
+
|
66 |
+
@app.route('/')
|
67 |
+
def index():
|
68 |
+
"""Home page displaying current programs and model status."""
|
69 |
+
return render_template('index.html', programs=programs, model_name=current_model_name)
|
70 |
+
|
71 |
+
@app.route('/set_model', methods=['POST'])
|
72 |
+
def set_model():
|
73 |
+
"""Allows users to dynamically change the model."""
|
74 |
+
global tokenizer, model, plo_embeddings, current_model_name
|
75 |
+
|
76 |
+
model_name = request.form['model_name']
|
77 |
+
tokenizer, model, error = load_model_and_tokenizer(model_name)
|
78 |
+
|
79 |
+
if error:
|
80 |
+
return render_template('index.html', programs=programs, message=f"Error loading model: {error}")
|
81 |
+
|
82 |
+
# Update the global model name and recompute embeddings
|
83 |
+
current_model_name = model_name
|
84 |
+
plo_embeddings = compute_plo_embeddings()
|
85 |
+
return redirect(url_for('index'))
|
86 |
+
|
87 |
+
@app.route('/addprogram', methods=['GET', 'POST'])
|
88 |
+
def add_program():
|
89 |
+
"""Adds a new program."""
|
90 |
+
if request.method == 'POST':
|
91 |
+
program_name = request.form['program_name']
|
92 |
+
if program_name not in programs:
|
93 |
+
programs[program_name] = {} # Initialize an empty dictionary for courses
|
94 |
+
return redirect(url_for('index'))
|
95 |
+
return render_template('addprogram.html')
|
96 |
+
|
97 |
+
@app.route('/addcourse', methods=['GET', 'POST'])
|
98 |
+
def create_course():
|
99 |
+
"""Creates a new course under a specific program."""
|
100 |
+
if request.method == 'POST':
|
101 |
+
program_name = request.form['program']
|
102 |
+
course_name = request.form['course_name']
|
103 |
+
outcomes = request.form['course_outcomes'].split('\n')
|
104 |
+
|
105 |
+
if program_name in programs:
|
106 |
+
programs[program_name][course_name] = outcomes # Add course to the selected program
|
107 |
+
|
108 |
+
return redirect(url_for('index'))
|
109 |
+
return render_template('addcourse.html', programs=programs)
|
110 |
+
|
111 |
+
@app.route('/match', methods=['POST'])
|
112 |
+
def match_outcomes():
|
113 |
+
"""Matches course outcomes with predefined PLOs."""
|
114 |
+
course_name = request.form['course']
|
115 |
+
print(course_name)
|
116 |
+
course_outcomes = request.form['course_outcomes'].split('\n')
|
117 |
+
results = []
|
118 |
+
|
119 |
+
for co in course_outcomes:
|
120 |
+
co = co.strip()
|
121 |
+
if co: # Ensure the outcome is not empty
|
122 |
+
similarities = get_similarity(co)
|
123 |
+
top_matches_indices = similarities.topk(3).indices.tolist()
|
124 |
+
results.append({
|
125 |
+
'course_outcome': co,
|
126 |
+
'course_name' : course_name,
|
127 |
+
'best_matches': top_matches_indices
|
128 |
+
})
|
129 |
+
|
130 |
+
return render_template('result.html', course_name =course_name, results=results)
|
131 |
+
|
132 |
+
if __name__ == '__main__':
|
133 |
+
app.run(debug=True)
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Flask
|
2 |
+
transformers
|
3 |
+
torch
|
4 |
+
Gunicorn
|
5 |
+
pandas
|
6 |
+
openpyxl
|
templates/addcourse.html
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>Add Course</title>
|
6 |
+
</head>
|
7 |
+
<body>
|
8 |
+
<h1>Add a New Course</h1>
|
9 |
+
<form action="/addcourse" method="post">
|
10 |
+
<label for="program">Select Program:</label><br>
|
11 |
+
<select id="program" name="program" required>
|
12 |
+
<option value="">--Select a program--</option>
|
13 |
+
{% for program in programs %}
|
14 |
+
<option value="{{ program }}">{{ program }}</option>
|
15 |
+
{% endfor %}
|
16 |
+
</select><br><br>
|
17 |
+
|
18 |
+
<label for="course_name">Course Name:</label><br>
|
19 |
+
<input type="text" id="course_name" name="course_name" required><br><br>
|
20 |
+
|
21 |
+
<label for="course_outcomes">Course Learning Outcomes (one per line):</label><br>
|
22 |
+
<textarea id="course_outcomes" name="course_outcomes" rows="5" cols="50" required></textarea><br><br>
|
23 |
+
|
24 |
+
<input type="submit" value="Add Course">
|
25 |
+
</form>
|
26 |
+
<br>
|
27 |
+
<a href="/">Back to Home</a>
|
28 |
+
</body>
|
29 |
+
</html>
|
templates/addprogram.html
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Add Program</title>
|
7 |
+
</head>
|
8 |
+
<body>
|
9 |
+
<h1>Add a New Program</h1>
|
10 |
+
<form action="/addprogram" method="post">
|
11 |
+
<label for="program_name">Program Name:</label><br>
|
12 |
+
<input type="text" id="program_name" name="program_name" required><br><br>
|
13 |
+
<input type="submit" value="Add Program">
|
14 |
+
</form>
|
15 |
+
<br>
|
16 |
+
<a href="/">Back to Home</a>
|
17 |
+
</body>
|
18 |
+
</html>
|
templates/index.html
ADDED
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
7 |
+
<title>Fibrosis</title>
|
8 |
+
<link rel="shortcut icon"
|
9 |
+
href="" />
|
10 |
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
11 |
+
<style>
|
12 |
+
body{background-color: #eff2f9;}
|
13 |
+
.iupload h3{color: #1b2d6b;font-size: 30px;font-weight: 700;}
|
14 |
+
.img-part{height:300px;width:300px;margin:0px auto;}
|
15 |
+
.image-part{height:300px;width:300px;border:1px solid #1b2d6b;}
|
16 |
+
.image-part img{position:absolute;height: 300px;width:300px;display:none;padding:5px;}
|
17 |
+
.image-part #video{display:block;height: 300px;width:300px;padding:5px;}
|
18 |
+
.res-part{border:1px solid #dedede;margin-left:20px;height: 310px;width:100%;padding:5px;margin:0px auto;overflow:auto;}
|
19 |
+
.res-part2{border:1px solid #dedede;height: 310px;width:100%;padding:5px;margin:0px auto;}
|
20 |
+
.resp-img{height: 298px;width: 233px;margin:0px auto;}
|
21 |
+
.jsonRes{margin-left:30px;}
|
22 |
+
#send{cursor:pointer;}
|
23 |
+
.btn-part{width:325px;}
|
24 |
+
textarea,
|
25 |
+
select,
|
26 |
+
.form-control,
|
27 |
+
.custom-select,
|
28 |
+
button.btn,
|
29 |
+
.btn-primary,
|
30 |
+
input[type="text"],
|
31 |
+
input[type="url"],
|
32 |
+
.uneditable-input{
|
33 |
+
border: 1px solid #363e75;
|
34 |
+
outline: 0 !important;
|
35 |
+
border-radius:0px;
|
36 |
+
box-shadow: none;
|
37 |
+
-webkit-box-shadow: none;
|
38 |
+
-moz-box-shadow: none;
|
39 |
+
-moz-transition: none;
|
40 |
+
-webkit-transition: none;
|
41 |
+
}
|
42 |
+
textarea:focus,
|
43 |
+
select:focus,
|
44 |
+
.form-control:focus,
|
45 |
+
.btn:focus,
|
46 |
+
.btn-primary:focus,
|
47 |
+
.custom-select:focus,
|
48 |
+
input[type="text"]:focus,
|
49 |
+
.uneditable-input:focus{
|
50 |
+
border: 1px solid #007bff;
|
51 |
+
outline: 0 !important;
|
52 |
+
border-radius:0px;
|
53 |
+
box-shadow: none;
|
54 |
+
-webkit-box-shadow: none;
|
55 |
+
-moz-box-shadow: none;
|
56 |
+
-moz-transition: none;
|
57 |
+
-webkit-transition: none;
|
58 |
+
}
|
59 |
+
#loading {
|
60 |
+
position: fixed;
|
61 |
+
left: 0px;
|
62 |
+
top: 0px;
|
63 |
+
width: 100%;
|
64 |
+
height: 100%;
|
65 |
+
z-index: 9999999999;
|
66 |
+
overflow: hidden;
|
67 |
+
background: rgba(255, 255, 255, 0.7);
|
68 |
+
}
|
69 |
+
.loader {
|
70 |
+
border: 8px solid #f3f3f3;
|
71 |
+
border-top: 8px solid #363e75;
|
72 |
+
border-radius: 50%;
|
73 |
+
width: 60px;
|
74 |
+
height: 60px;
|
75 |
+
left: 50%;
|
76 |
+
margin-left: -4em;
|
77 |
+
display: block;
|
78 |
+
animation: spin 2s linear infinite;
|
79 |
+
}
|
80 |
+
.loader,
|
81 |
+
.loader:after {display: block;position: absolute;top: 50%;margin-top: -4.05em;}
|
82 |
+
@keyframes spin {
|
83 |
+
0% {
|
84 |
+
transform: rotate(0deg);
|
85 |
+
}
|
86 |
+
100% {
|
87 |
+
transform: rotate(360deg);
|
88 |
+
}
|
89 |
+
}
|
90 |
+
.right-part{border:1px solid #dedede;padding:5px;}
|
91 |
+
.logo{position:absolute;right:0px;bottom:0px;margin-right:30px;margin-bottom:30px;}
|
92 |
+
</style>
|
93 |
+
<script>
|
94 |
+
let programs = {{ programs|tojson }}; // Passing programs from the backend as a JSON object
|
95 |
+
|
96 |
+
// Update the courses dropdown when a program is selected
|
97 |
+
function updateCourses() {
|
98 |
+
const programSelect = document.getElementById("program");
|
99 |
+
const courseSelect = document.getElementById("course");
|
100 |
+
const selectedProgram = programSelect.value;
|
101 |
+
|
102 |
+
// Clear existing options in the course dropdown
|
103 |
+
courseSelect.innerHTML = "<option value=''>--Select a course--</option>";
|
104 |
+
document.getElementById("course_outcomes").value = ""; // Clear the course outcomes
|
105 |
+
|
106 |
+
if (selectedProgram && programs[selectedProgram]) {
|
107 |
+
const courses = Object.keys(programs[selectedProgram]);
|
108 |
+
courses.forEach(course => {
|
109 |
+
let option = document.createElement("option");
|
110 |
+
option.value = course;
|
111 |
+
option.text = course;
|
112 |
+
courseSelect.appendChild(option);
|
113 |
+
});
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
// Update the course outcomes in the listbox when a course is selected
|
118 |
+
function updateCourseOutcomes() {
|
119 |
+
const programSelect = document.getElementById("program").value;
|
120 |
+
const courseSelect = document.getElementById("course").value;
|
121 |
+
const courseOutcomes = programs[programSelect] ? programs[programSelect][courseSelect] : [];
|
122 |
+
|
123 |
+
const courseOutcomesTextArea = document.getElementById("course_outcomes");
|
124 |
+
courseOutcomesTextArea.value = courseOutcomes ? courseOutcomes.join("\n") : "";
|
125 |
+
}
|
126 |
+
</script>
|
127 |
+
</head>
|
128 |
+
<body>
|
129 |
+
<div class="main container">
|
130 |
+
<section class="iupload">
|
131 |
+
<h3 class="text-center py-4">CLOs - PLOs Mapping Using Large Language Models </h3>
|
132 |
+
<div class="row">
|
133 |
+
<div class="img-part col-md-6">
|
134 |
+
<h1> </h1>
|
135 |
+
|
136 |
+
<!-- Section for Model Selection -->
|
137 |
+
<h5>Select Model</h5>
|
138 |
+
<form action="/set_model" method="post">
|
139 |
+
<label for="model_name">Choose a Model:</label><br>
|
140 |
+
<select id="model_name" name="model_name">
|
141 |
+
<option value="sentence-transformers/all-mpnet-base-v2" selected>all-mpnet-base-v2</option>
|
142 |
+
<option value="sentence-transformers/bert-base-nli-mean-tokens">bert-base-nli-mean-tokens</option>
|
143 |
+
<option value="thuan9889/llama_embedding_model_v1">llama_embedding_model_v1</option>
|
144 |
+
<option value="sembeddings/model_gpt_trained">model_gpt_trained</option>
|
145 |
+
</select>
|
146 |
+
<button type="submit">Set Model</button>
|
147 |
+
</form>
|
148 |
+
|
149 |
+
<h5>Current Model: {{ model_name }}</h5>
|
150 |
+
{% if message %}
|
151 |
+
<p style="color: red;">{{ message }}</p>
|
152 |
+
{% endif %}
|
153 |
+
|
154 |
+
<hr>
|
155 |
+
|
156 |
+
<!-- Section for Course Outcome Matching -->
|
157 |
+
<h5>Select Program and Course</h5>
|
158 |
+
<form action="/match" method="post">
|
159 |
+
<label for="program">Select Program:</label><br>
|
160 |
+
<select id="program" name="program" onChange="updateCourses()">
|
161 |
+
<option value="">--Select a program--</option>
|
162 |
+
{% for program in programs %}
|
163 |
+
<option value="{{ program }}">{{ program }}</option>
|
164 |
+
{% endfor %}
|
165 |
+
</select><br><br>
|
166 |
+
|
167 |
+
<label for="course">Select Course:</label><br>
|
168 |
+
<select id="course" name="course" onChange="updateCourseOutcomes()">
|
169 |
+
<option value="">--Select a course--</option>
|
170 |
+
</select><br><br>
|
171 |
+
|
172 |
+
<label for="course_outcomes">Course Outcomes:</label><br>
|
173 |
+
<textarea id="course_outcomes" name="course_outcomes" rows="10" cols="50" readonly></textarea><br><br>
|
174 |
+
|
175 |
+
<input type="submit" value="Submit">
|
176 |
+
</form>
|
177 |
+
</div>
|
178 |
+
<div class="col-md-6 col-xs-12 right-part">
|
179 |
+
<h5 class="mb-2"><center>Create a Program or Course</center></h5>
|
180 |
+
<div class="row">
|
181 |
+
|
182 |
+
<div class="res-part col-md-5 col-xs-12"><div class="jsonRes"><h2></h2>
|
183 |
+
<ul>
|
184 |
+
<li><a href="/addprogram">Create Program</a></li>
|
185 |
+
<li><a href="/addcourse">Create Course</a></li>
|
186 |
+
</ul></div></div>
|
187 |
+
</div>
|
188 |
+
</div>
|
189 |
+
</div>
|
190 |
+
</section>
|
191 |
+
</div>
|
192 |
+
|
193 |
+
<img class="logo" src="" />
|
194 |
+
|
195 |
+
|
196 |
+
<div id="loading"></div>
|
197 |
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
198 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
199 |
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
200 |
+
|
201 |
+
<script>
|
202 |
+
var mybtn = document.getElementById('startbtn');
|
203 |
+
var myvideo = document.getElementById('video');
|
204 |
+
var mycanvas = document.getElementById('canvas');
|
205 |
+
var myphoto = document.getElementById('photo');
|
206 |
+
var base_data = "";
|
207 |
+
|
208 |
+
function sendRequest(base64Data){
|
209 |
+
var type = "json";
|
210 |
+
if(base64Data != "" || base64Data != null){
|
211 |
+
if(type == "imgtobase"){
|
212 |
+
$(".res-part").html("");
|
213 |
+
$(".res-part").html(base64Data);
|
214 |
+
}
|
215 |
+
else if(type == "basetoimg"){
|
216 |
+
var imageData = $("#imgstring").val();
|
217 |
+
$(".res-part").html("");
|
218 |
+
$(".res-part").append("<img src='data:image/jpeg;base64," + imageData + "' alt='' />");
|
219 |
+
}
|
220 |
+
else{
|
221 |
+
var url = $("#url").val();
|
222 |
+
$("#loading").show();
|
223 |
+
$.ajax({
|
224 |
+
url : url,
|
225 |
+
type: "post",
|
226 |
+
cache: false,
|
227 |
+
async: true,
|
228 |
+
crossDomain: true,
|
229 |
+
headers: {
|
230 |
+
'Content-Type': 'application/json',
|
231 |
+
'Access-Control-Allow-Origin':'*'
|
232 |
+
},
|
233 |
+
data:JSON.stringify({image:base64Data}),
|
234 |
+
success: function(res){
|
235 |
+
$(".res-part").html("");
|
236 |
+
$(".res-part2").html("");
|
237 |
+
try{
|
238 |
+
var imageData = res[1].image;
|
239 |
+
if(imageData.length > 100){
|
240 |
+
if(imageData.length > 10){$(".res-part2").append("<img class='resp-img' src='data:image/jpeg;base64," + imageData + "' alt='' />");}
|
241 |
+
}
|
242 |
+
}catch(e){}
|
243 |
+
$(".res-part").html("<pre>" + JSON.stringify(res[0], undefined, 2) + "</pre>");
|
244 |
+
$("#loading").hide();
|
245 |
+
}
|
246 |
+
});
|
247 |
+
}
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
$(document).ready(function(){
|
252 |
+
$("#loading").hide();
|
253 |
+
|
254 |
+
$('#send').click(function(evt){
|
255 |
+
sendRequest(base_data);
|
256 |
+
});
|
257 |
+
|
258 |
+
$('#uload').click(function(evt) {
|
259 |
+
$('#fileinput').focus().trigger('click');
|
260 |
+
});
|
261 |
+
$("#fileinput").change(function(){
|
262 |
+
if (this.files && this.files[0]){
|
263 |
+
var reader = new FileReader();
|
264 |
+
reader.onload = function (e){
|
265 |
+
var url = e.target.result;
|
266 |
+
var img = new Image();
|
267 |
+
img.crossOrigin = 'Anonymous';
|
268 |
+
img.onload = function(){
|
269 |
+
var canvas = document.createElement('CANVAS');
|
270 |
+
var ctx = canvas.getContext('2d');
|
271 |
+
canvas.height = this.height;
|
272 |
+
canvas.width = this.width;
|
273 |
+
ctx.drawImage(this, 0, 0);
|
274 |
+
base_data = canvas.toDataURL('image/jpeg', 1.0).replace(/^data:image.+;base64,/, '');
|
275 |
+
canvas = null;
|
276 |
+
};
|
277 |
+
img.src = url;
|
278 |
+
$('#photo').attr('src', url);
|
279 |
+
$('#photo').show();
|
280 |
+
$('#video').hide();
|
281 |
+
}
|
282 |
+
reader.readAsDataURL(this.files[0]);
|
283 |
+
}
|
284 |
+
});
|
285 |
+
});
|
286 |
+
|
287 |
+
</script>
|
288 |
+
</body>
|
289 |
+
</html>
|
templates/result.html
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Predicted Mapping</title>
|
7 |
+
<style>
|
8 |
+
table, th, td {
|
9 |
+
border: 1px solid black;
|
10 |
+
border-collapse: collapse;
|
11 |
+
padding: 10px;
|
12 |
+
text-align: left;
|
13 |
+
}
|
14 |
+
.top-1 { background-color: red; }
|
15 |
+
.top-2 { background-color: blue; }
|
16 |
+
.top-3 { background-color: green; }
|
17 |
+
</style>
|
18 |
+
</head>
|
19 |
+
<body>
|
20 |
+
<h1>Predicted Mapping</h1>
|
21 |
+
<h2>Course: {{ course_name }}</h2>
|
22 |
+
<table>
|
23 |
+
<tr>
|
24 |
+
<th>Course Learning Outcome</th>
|
25 |
+
<th>PLO1</th>
|
26 |
+
<th>PLO2</th>
|
27 |
+
<th>PLO3</th>
|
28 |
+
<th>PLO4</th>
|
29 |
+
<th>PLO5</th>
|
30 |
+
<th>PLO6</th>
|
31 |
+
</tr>
|
32 |
+
{% for result in results %}
|
33 |
+
<tr>
|
34 |
+
<td>{{ result.course_outcome }}</td>
|
35 |
+
<td class="{% if 0 in result.best_matches[:1] %}top-1{% elif 0 in result.best_matches[1:2] %}top-2{% elif 0 in result.best_matches[2:3] %}top-3{% endif %}">{{ 'β' if 0 in result.best_matches else '' }}</td>
|
36 |
+
<td class="{% if 1 in result.best_matches[:1] %}top-1{% elif 1 in result.best_matches[1:2] %}top-2{% elif 1 in result.best_matches[2:3] %}top-3{% endif %}">{{ 'β' if 1 in result.best_matches else '' }}</td>
|
37 |
+
<td class="{% if 2 in result.best_matches[:1] %}top-1{% elif 2 in result.best_matches[1:2] %}top-2{% elif 2 in result.best_matches[2:3] %}top-3{% endif %}">{{ 'β' if 2 in result.best_matches else '' }}</td>
|
38 |
+
<td class="{% if 3 in result.best_matches[:1] %}top-1{% elif 3 in result.best_matches[1:2] %}top-2{% elif 3 in result.best_matches[2:3] %}top-3{% endif %}">{{ 'β' if 3 in result.best_matches else '' }}</td>
|
39 |
+
<td class="{% if 4 in result.best_matches[:1] %}top-1{% elif 4 in result.best_matches[1:2] %}top-2{% elif 4 in result.best_matches[2:3] %}top-3{% endif %}">{{ 'β' if 4 in result.best_matches else '' }}</td>
|
40 |
+
<td class="{% if 5 in result.best_matches[:1] %}top-1{% elif 5 in result.best_matches[1:2] %}top-2{% elif 5 in result.best_matches[2:3] %}top-3{% endif %}">{{ 'β' if 5 in result.best_matches else '' }}</td>
|
41 |
+
</tr>
|
42 |
+
{% endfor %}
|
43 |
+
</table>
|
44 |
+
<a href="/">Back to Input</a>
|
45 |
+
</body>
|
46 |
+
</html>
|