Skip to content

Commit 5096122

Browse files
committed
new improvements
- seprated insights & share_scores into different functions - renamed methods in analyze.py - wrote some docs for insights
1 parent a796b3f commit 5096122

File tree

6 files changed

+95
-47
lines changed

6 files changed

+95
-47
lines changed

demo.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
"""Usage example"""
22
import os
33
import pprint
4-
from plagcheck import plagcheck
4+
from plagcheck.plagcheck import check, insights, share_scores
55

66
from dotenv import load_dotenv
77
load_dotenv()
88

9-
language = "python"
9+
language = "java"
1010
userid = os.environ["USER_ID"]
1111

1212

13-
moss = plagcheck.check(language, userid)
13+
moss = check(language, userid)
1414

15-
moss.addFilesByWildCard("testfiles/test_python*.py")
15+
moss.addFilesByWildCard("testfiles/test_java*.java")
1616

1717
# or moss.addFile("testfiles/test_python.py")
1818

1919
moss.submit()
2020

2121
print(moss.getHomePage())
22-
pprint.pprint(moss.getResults())
23-
# print frequency of each shared solution
24-
pprint.pprint(moss.getShareScores())
22+
23+
result = moss.getResults()
24+
25+
pprint.pprint(result)
26+
2527
# print potential distributor-culprit relationships
26-
pprint.pprint(moss.getInsights())
28+
pprint.pprint(insights(result))
29+
# print frequency of each shared solution
30+
pprint.pprint(share_scores(result))

docs/insights.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Insights
2+
3+
PlagCheck provides algorithmic analysis of Moss results.
4+
5+
6+
## M-group
7+
m-groups (moss-groups) are groups of solution which have similar code.
8+
For example A student who solves a programming problem may share their
9+
solution with 3 of his/her friends, that is a single m-group with 4 nodes.
10+
11+
For example if you run [demo.py](https://github.com/codeclassroom/PlagCheck/blob/master/demo.py), `insights()` will return the following data:
12+
```python
13+
14+
{'DCtoC Paths': [('testfiles/test_java5.java', 'testfiles/test_java2.java'),
15+
('testfiles/test_java4.java', 'testfiles/test_java2.java')],
16+
'DtoC Paths': [('testfiles/test_java3.java', 'testfiles/test_java2.java'),
17+
('testfiles/test_java3.java', 'testfiles/test_java.java'),
18+
('testfiles/test_java7.java', 'testfiles/test_java6.java')],
19+
'DtoDC Paths': [('testfiles/test_java3.java', 'testfiles/test_java5.java'),
20+
('testfiles/test_java3.java', 'testfiles/test_java4.java')]}
21+
22+
```
23+
24+
This analysis can be visulaized into following _Disconnected Directed Graph_
25+
26+
![moss results](https://drive.google.com/uc?export=view&id=1Lc8obgjihfo7EGimn300mTtqfmHK0Zem)
27+
28+
We assign Tags to every individual file which has been returned by Moss.
29+
30+
1. D - Distributor
31+
Student(s) who distributed their
32+
code in a group.
33+
2. C - Culprit
34+
Student(s) who copied the shared
35+
code.
36+
3. DC - Both a Distributor & Culprit
37+
38+
In the above depicted graph, there are 2 unique _m-groups_.
39+
40+
1. Group 1 : [1, 2, 3, 4, 5]
41+
2. Group 2 : [7, 6]

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ nav:
88
- Documentation: index.md
99
- Installation: installation.md
1010
- Usage: usage.md
11+
- Insights: insights.md
1112
- Moss: moss.md
1213
- Changelog: changelog.md
1314
- About: about.md

plagcheck/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""The MOSS interface package for CodeClassroom"""
2-
from plagcheck.plagcheck import check
2+
from plagcheck.plagcheck import check, insights, share_scores

plagcheck/analyze.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def __init__(self):
2828
self.nodes = []
2929
self.nodeCount = 0
3030

31-
def relatesTo(self, P1, P2, node1, node2):
31+
def relate(self, P1, P2, node1, node2):
3232
"""Set a path between two file nodes"""
3333
node_obj_dict = {}
3434

plagcheck/plagcheck.py

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,45 @@ def request(url: str):
4343
return req.decode("utf-8")
4444

4545

46+
def share_scores(moss_data: dict) -> dict:
47+
"""Share Score Insights"""
48+
similar_code_files = []
49+
for result in moss_data:
50+
similar_code_files.append(result["file1"])
51+
similar_code_files.append(result["file2"])
52+
53+
# frequency of files which are similar
54+
share_score = collections.Counter(similar_code_files)
55+
56+
return dict(share_score)
57+
58+
59+
def insights(moss_data: dict) -> dict:
60+
"""Analysis for Moss"""
61+
mg = Mgroups()
62+
similar_code_files = set()
63+
insights = {}
64+
65+
for r in moss_data:
66+
similar_code_files.add(r["file1"])
67+
similar_code_files.add(r["file2"])
68+
69+
mg.createNodes(similar_code_files)
70+
71+
for r in moss_data:
72+
mg.relate(
73+
r["percentage_file1"], r["percentage_file2"], r["file1"], r["file2"]
74+
)
75+
76+
mg.set_tags()
77+
78+
insights["DtoC Paths"] = mg.d2c()
79+
insights["DtoDC Paths"] = mg.d2dc()
80+
insights["DCtoC Paths"] = mg.dc2c()
81+
82+
return insights
83+
84+
4685
class check:
4786
"""
4887
Args:
@@ -133,40 +172,3 @@ def getResults(self) -> Tuple[str, Results]:
133172
"""Return the result as a list of dictionary"""
134173

135174
return self.moss_results
136-
137-
def getShareScores(self):
138-
"""Share Score Insights"""
139-
similar_code_files = []
140-
for result in self.moss_results:
141-
similar_code_files.append(result["file1"])
142-
similar_code_files.append(result["file2"])
143-
144-
# frequency of files which are similar
145-
share_score = collections.Counter(similar_code_files)
146-
147-
return dict(share_score)
148-
149-
def getInsights(self):
150-
"""Analysis for Moss"""
151-
mg = Mgroups()
152-
similar_code_files = set()
153-
insights = {}
154-
155-
for r in self.moss_results:
156-
similar_code_files.add(r["file1"])
157-
similar_code_files.add(r["file2"])
158-
159-
mg.createNodes(similar_code_files)
160-
161-
for r in self.moss_results:
162-
mg.relatesTo(
163-
r["percentage_file1"], r["percentage_file2"], r["file1"], r["file2"]
164-
)
165-
166-
mg.set_tags()
167-
168-
insights["DtoC Paths"] = mg.d2c()
169-
insights["DtoDC Paths"] = mg.d2dc()
170-
insights["DCtoC Paths"] = mg.dc2c()
171-
172-
return insights

0 commit comments

Comments
 (0)