-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
723 additions
and
162 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,97 @@ | ||
// 根据 DAG 描述构建图 | ||
function buildGraph(dag, nodeValueToLabel) { | ||
const graph = {}; | ||
const lines = dag.trim().split('\n'); | ||
|
||
for (const line of lines) { | ||
const [node, ...parents] = line.split(':').map(item => item.trim()); | ||
const label = nodeValueToLabel[node]; | ||
if (parents.length === 0 || parents[0] === '') { | ||
graph[label] = []; | ||
} else { | ||
const validParents = parents.map(parent => nodeValueToLabel[parent]).filter(parent => parent !== ''); | ||
graph[label] = validParents; | ||
} | ||
} | ||
|
||
return graph; | ||
const graph = {}; | ||
const inDegree = {}; | ||
|
||
// initialize graph and in-degree | ||
for (const nodeLabel in nodeValueToLabel) { | ||
graph[nodeLabel] = []; | ||
inDegree[nodeLabel] = 0; | ||
} | ||
|
||
// 构建入度数组并初始化队列 | ||
function initializeCounts(graph) { | ||
const inDegree = {}; | ||
const queue = []; | ||
|
||
for (const node in graph) { | ||
inDegree[node] = graph[node].length; | ||
if (inDegree[node] === 0) { | ||
queue.push(node); | ||
|
||
// parse the DAG and build the graph | ||
const lines = dag.split('\n'); | ||
for (const line of lines) { | ||
const parts = line.split(':').map(part => part.trim()); | ||
if (parts.length === 2) { | ||
const nodeLabel = parts[0]; | ||
const dependencies = parts[1].split(' ').filter(label => label !== ''); | ||
for (const dependency of dependencies) { | ||
if (dependency !== '-1' && nodeValueToLabel[nodeLabel] !== undefined && nodeValueToLabel[dependency] !== undefined) { | ||
graph[nodeLabel].push(dependency); // add dependency to the graph | ||
inDegree[dependency]++; // increment in-degree of the dependency | ||
} | ||
} | ||
} | ||
|
||
return { inDegree, queue }; | ||
} | ||
|
||
|
||
function processSolution(graph, inDegree, queue, solution, nodeValueToLabel) { | ||
const visited = new Set(); | ||
if (Array.isArray(solution)) { | ||
solution = solution.join('\n'); | ||
} else if (typeof solution !== 'string') { | ||
throw new TypeError('The solution must be a string or an array.'); | ||
} | ||
|
||
const solutionNodes = solution.split('\n').map(line => line.trim()); | ||
const graphNodes = Object.keys(graph).filter(node => node !== '__root__'); // 排除虚拟根节点 | ||
|
||
console.log("Solution nodes:", solutionNodes); | ||
console.log("Graph nodes:", graphNodes); | ||
|
||
// 检查学生的解答中的项目数量是否与图中的节点数量匹配 | ||
if (solutionNodes.length !== graphNodes.length) { | ||
throw new Error('Number of items in student solution does not match the number of nodes in the graph.'); | ||
console.log("Graph:", graph); | ||
console.log("In-degree:", inDegree); | ||
return { graph, inDegree }; | ||
} | ||
|
||
|
||
function processSolution(solution, graph, inDegree, nodeValueToLabel) { | ||
console.log("processSolution:", solution); | ||
console.log("processnodeValueToLabel:", nodeValueToLabel); | ||
const visited = new Set(); | ||
|
||
for (const nodeText of solution) { | ||
const nodeLabel = Object.keys(nodeValueToLabel).find( | ||
(label) => nodeValueToLabel[label] === nodeText | ||
); | ||
|
||
if (nodeLabel === undefined) { | ||
console.log("Skipping node not found in nodeValueToLabel:", nodeText); | ||
continue; // jump to the next node | ||
} | ||
|
||
for (const node of solutionNodes) { // 修改这里 | ||
console.log("Current node:", node); | ||
console.log("Current queue:", queue); | ||
|
||
// 查找节点对应的标签 | ||
const label = node; // 修改这里 | ||
if (!label) { | ||
console.log("Node label not found, returning false"); | ||
return false; | ||
} | ||
|
||
// 如果当前节点的标签不在队列中,返回false | ||
if (!queue.includes(label)) { | ||
console.log("Node label not in queue, returning false"); | ||
|
||
console.log('Current label:', nodeLabel); | ||
console.log('Current node text:', nodeText); | ||
console.log('Node value to label mapping:', nodeValueToLabel); | ||
|
||
visited.add(nodeLabel); | ||
|
||
// check if the node has dependencies | ||
for (const dependencyLabel of graph[nodeLabel]) { | ||
if (!visited.has(dependencyLabel)) { | ||
console.error("Dependency not satisfied:", nodeText, "depends on", nodeValueToLabel[dependencyLabel]); | ||
return false; | ||
} | ||
|
||
// 将当前节点的标签从队列中移除 | ||
queue.splice(queue.indexOf(label), 1); | ||
visited.add(label); | ||
|
||
// 更新相邻节点的入度,并将入度变为0的节点加入队列 | ||
for (const neighbor in graph) { | ||
if (graph[neighbor].includes(label)) { | ||
inDegree[neighbor]--; | ||
if (inDegree[neighbor] === 0) { | ||
queue.push(neighbor); | ||
} | ||
} | ||
} | ||
console.log("Updated in-degree:", inDegree); | ||
console.log("Updated queue:", queue); | ||
} | ||
|
||
// 如果所有节点都被访问过,返回true,否则返回false | ||
const allVisited = visited.size === Object.keys(graph).length; | ||
console.log("All nodes visited:", allVisited); | ||
return allVisited; | ||
} | ||
|
||
// check if all nodes were visited | ||
if (visited.size !== Object.keys(nodeValueToLabel).length) { | ||
console.error("Not all nodes in nodeValueToLabel were visited."); | ||
return false; | ||
} | ||
|
||
console.log('Visited nodes:', Array.from(visited)); | ||
return true; | ||
} | ||
|
||
|
||
|
||
|
||
function processDAG(dag, solution) { | ||
const nodeValueToLabel = { | ||
"one": "print('Hello')", | ||
"two": "print('Parsons')", | ||
"three": "print('Problems!')" | ||
}; | ||
|
||
const graph = buildGraph(dag, nodeValueToLabel); | ||
const { inDegree, queue } = initializeCounts(graph); | ||
const result = processSolution(graph, inDegree, queue, solution, nodeValueToLabel); | ||
return result; | ||
function processDAG(dag, solution, nodeValueToLabel) { | ||
console.log("DAG:", dag); | ||
console.log("Node value to label mapping:", nodeValueToLabel); | ||
const { graph, inDegree } = buildGraph(dag, nodeValueToLabel); | ||
const result = processSolution(solution, graph, inDegree, nodeValueToLabel); | ||
return result; | ||
} | ||
|
||
function extractCode(solution, nodeValueToLabel) { | ||
const code = []; | ||
const newNodeValueToLabel = {}; | ||
for (const nodeText of solution) { | ||
const nodeLabel = Object.keys(nodeValueToLabel).find( | ||
(key) => nodeValueToLabel[key] === nodeText | ||
); | ||
if (nodeLabel !== undefined) { | ||
code.push(nodeText); | ||
newNodeValueToLabel[nodeLabel] = nodeText; | ||
} | ||
} | ||
return { code, newNodeValueToLabel }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,28 @@ | ||
# == Schema Information | ||
# | ||
# Table name: parsons_prompts | ||
# | ||
# id :integer not null, primary key | ||
# assets :text(65535) | ||
# instructions :text(65535) | ||
# title :text(65535) | ||
# created_at :datetime | ||
# updated_at :datetime | ||
# exercise_id :string(255) | ||
# exercise_version_id :integer not null | ||
# | ||
# Indexes | ||
# | ||
# fk_rails_40d6ef5b4f (exercise_version_id) | ||
# | ||
# Foreign Keys | ||
# | ||
# fk_rails_... (exercise_version_id => exercise_versions.id) | ||
# | ||
|
||
class ParsonsPrompt < ActiveRecord::Base | ||
belongs_to :parsons | ||
belongs_to :exercise_version | ||
|
||
store_accessor :assets, :code, :test | ||
end | ||
serialize :assets, JSON | ||
end |
Oops, something went wrong.