Skip to content

Commit

Permalink
Add TFG-visualizer
Browse files Browse the repository at this point in the history
  • Loading branch information
Isla-top committed Dec 2, 2023
1 parent a14dfc1 commit 914cd31
Show file tree
Hide file tree
Showing 10 changed files with 1,339 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/main/ts/index.html
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + TS</title>
</head>
<body>
<div id="input" style="width: 300px; height: 200px; white-space: pre; border: 1px solid black;">
拖拽文件进入此处
</div>
<div class="button-container" id="buttonContainer"></div>
<script type="module" src="/src/main.ts"></script>
<div id="myDiagramDiv" style="width: 1100px; height: 800px; border: 1px solid black;"></div>
<!-- <script type="module" src="/src/main.ts"></script> -->
</body>
</html>
21 changes: 21 additions & 0 deletions src/main/ts/package.json
@@ -0,0 +1,21 @@
{
"name": "test-ts3",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"devDependencies": {
"@types/js-yaml": "^4.0.5",
"typescript": "^5.0.2",
"vite": "^4.3.2"
},
"dependencies": {
"gojs": "^2.3.7",
"js-yaml": "^4.1.0",
"yaml": "^2.3.0-5"
}
}
427 changes: 427 additions & 0 deletions src/main/ts/pnpm-lock.yaml

Large diffs are not rendered by default.

152 changes: 152 additions & 0 deletions src/main/ts/src/graph.ts
@@ -0,0 +1,152 @@
import { parse } from "yaml";

export class Graph{
metadata: Metadata;
relation: Relation;
graph: Map<number, number[]>;
sourceNodes: number[];
sinkNodes: number[];
recommendedPaths: number[][];

constructor(data: any){
this.metadata = new Metadata(data.metadata);
this.relation = new Relation(data.relation, this.metadata);
this.graph = new Map();
this.initGraph(data.graph);
this.sourceNodes = data.sourceNodes;
this.sinkNodes = data.sinkNodes;

this.recommendedPaths = (data.recommendedPaths as number[][]).map(path=>path.filter(n => !this.isField(n)));
// console.log(this.recommandedPaths);
// console.log(this.sourceNodes + " " + this.sinkNodes)
// console.log(this.metadata.getvf(6))
// console.log(this.metadata.getvf(25))
// console.log(this.metadata.getvf(26))
// console.log(this.metadata.getvf(27))
}

initGraph(graph: any){
Object.entries(graph).forEach(entry=>{
const toNodess: number[] = [];
(entry[1] as number[]).forEach(n=>{
if(this.isField(n)){
toNodess.push(...(graph[n] as number[]));
}else{
toNodess.push(n);
}
});
const toNodes = Array.from(new Set(toNodess));
this.graph.set(parseInt(entry[0]), toNodes);
});
}

isField(num:number){
return this.relation.fields.includes(num);
}

isSource(num:number){
return this.sourceNodes.includes(num);
}

isSink(num:number){
return this.sinkNodes.includes(num);
}
}

class Metadata{
packages: string[];
classes: string[];
methods: string[];
varsAndFields: string[];

constructor(metadata: any){
this.packages = metadata.packages;
this.classes = metadata.classes;
this.methods = metadata.methods;
this.varsAndFields = metadata.varsAndFields;

const len: number = this.classes.length;
for(let i = 0; i < len; i++){
if(!this.classes[i].includes('.')){
// set the class with no parent package different to its package
this.classes[i] = '.' + this.classes[i];
}
}
}

getp(index: number) {
return this.packages[index];
}

getc(index: number) {
return this.classes[index];
}

getm(index: number) {
return this.methods[index];
}

getvf(index: number) {
return this.varsAndFields[index];
}
}

class Relation{
packageToClasses: Map<number, number[]>;
classToMethods: Map<number, number[]>;
methodToVars: Map<number, number[]>;

fields: number[];
// jdkVars: number[];

constructor(relation: any, metadata: Metadata){
this.packageToClasses = new Map();
this.classToMethods = new Map();
this.methodToVars = new Map();
this.fields = Object.values(relation.classToFields).flat() as number[];

// const jdkPackages: number[] = [];
Object.entries(relation.packageToClasses).forEach(entry=>{
this.packageToClasses.set(parseInt(entry[0]), entry[1] as number[]);
// if(metadata.getp(parseInt(entry[0])) === "java.lang"){ // todo:
// jdkPackages.push(parseInt(entry[0]));
// }
});

Object.entries(relation.classToMethods).forEach(entry=>{
this.classToMethods.set(parseInt(entry[0]), entry[1] as number[]);
});

Object.entries(relation.methodToVars).forEach(entry=>{
this.methodToVars.set(parseInt(entry[0]), entry[1] as number[]);
});

// const jdkClasses: number[] = (Array.from(jdkPackages, p => this.packageToClasses.get(p)).flat().filter(item => item !== undefined) as number[]);
// const jdkMethods: number[] = (Array.from(jdkClasses, p => this.classToMethods.get(p)).flat().filter(item => item !== undefined) as number[]);
// this.jdkVars = (Array.from(jdkMethods, p => this.methodToVars.get(p)).flat().filter(item => item !== undefined) as number[]);
}

}

export function build(file:File, visualize:(graph:Graph)=>void){
const reader = new FileReader();

reader.onload = function(e){
const yamlContent = e.target?.result;
if(typeof yamlContent != 'string'){
console.log('yamlContent不是字符串类型');
return;
}
// try{
const parsedData = parse((yamlContent as string));
const graph:Graph = new Graph(parsedData);
console.log('finish build, begin visualization');
visualize(graph);
// }
// catch{
// console.log(e);
// }
}

reader.readAsText(file);
}
33 changes: 33 additions & 0 deletions src/main/ts/src/handle-event.ts
@@ -0,0 +1,33 @@
export function eventHandler(elem: HTMLElement, fileHandler: (file: File)=>void){
elem.addEventListener('dragenter', function(event) {
event.preventDefault();
elem.style.background = '#f7f7f7';
elem.textContent = "松开文件进行处理";
});
elem.addEventListener('dragleave', function(event) {
event.preventDefault();
elem.style.background = '#ffffff';
elem.textContent = "拖拽文件进入此处";
});
elem.addEventListener('dragover', function(event) {
event.preventDefault();
});
elem.addEventListener('drop', function(event){
event.preventDefault();
elem.style.background = '#ffffff';

let file = (event as DragEvent).dataTransfer?.files[0];

if(file === undefined){
elem.textContent = "未接收到文件";
return;
}
if(!file.name.endsWith('.yml')){
elem.textContent = "接收到非yaml文件";
return;
}
elem.textContent = "拖拽文件进入此处";
console.log('handle event over, begin building graph');
fileHandler(file);
});
}
10 changes: 10 additions & 0 deletions src/main/ts/src/main.ts
@@ -0,0 +1,10 @@
import './style.css'
import { build } from './graph'
import { eventHandler } from './handle-event'
import { visualize } from './visualization';

const inputElem: HTMLElement = document.getElementById('input') as HTMLElement;
eventHandler(inputElem, (file: File)=>{
build(file, visualize);
});

106 changes: 106 additions & 0 deletions src/main/ts/src/style.css
@@ -0,0 +1,106 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;

color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;

font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}

a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}

body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}

h1 {
font-size: 3.2em;
line-height: 1.1;
}

#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vanilla:hover {
filter: drop-shadow(0 0 2em #3178c6aa);
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}

.button-container {
position: absolute; /* 设置容器为绝对定位 */
top: 40px; /* 距离页面顶部 40px */
left: 20px; /* 距离页面左侧 20px */
display: flex; /* 使用 flexbox 布局 */
flex-direction: column; /* 设置为垂直排列 */
}

button {
border-radius: 8px;
border: 1px solid #1a1a1a;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
margin-bottom: 10px;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}

@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

0 comments on commit 914cd31

Please sign in to comment.