├── .gitignore ├── app.wsgi ├── page ├── index.html ├── js │ ├── checklogin.js │ ├── checknotlogin.js │ ├── login.js │ ├── reg.js │ ├── common.js │ ├── setting.js │ ├── project.js │ ├── history.js │ ├── rsrc.js │ ├── message.js │ ├── util.js │ ├── mining.js │ └── result.js ├── img │ ├── bg.png │ └── loading.gif ├── logout.html ├── css │ └── main.css ├── login.html ├── reg.html ├── message.html ├── rsrc.html ├── project.html ├── history.html ├── setting.html ├── result.html └── mining.html ├── doc ├── img │ ├── db.png │ ├── knn.png │ ├── pages.png │ ├── apriori.jpg │ ├── dm-page.png │ ├── graham.png │ ├── kmeans.png │ ├── assoc-csv.png │ ├── assoc-dist.png │ ├── dm-process.png │ ├── dm-top-10.png │ ├── dv-process.png │ ├── getCookie.png │ ├── gramham-eg.gif │ ├── kmedoids.png │ ├── orm-static.png │ ├── other-csv.png │ ├── other-dist.png │ ├── pages-arch.png │ ├── rmp-model.png │ ├── rsrc-page.png │ ├── use-case.png │ ├── algo-module.png │ ├── apriori-impl.png │ ├── assoc-total.png │ ├── entire-arch.png │ ├── history-page.png │ ├── kmeoids-ompl.png │ ├── message-page.png │ ├── other-total.png │ ├── project-page.png │ ├── seperate-mvc.png │ ├── setting-page.png │ ├── dm-req-process.png │ ├── rmp-comp-rsrc.png │ ├── rmp-single-rsrc.png │ ├── toolkit-archi.png │ ├── traditional-mvc.png │ ├── assoc-dist-chart.png │ ├── assoc-result-page.png │ ├── assoc-total-chart.png │ ├── front-end-process.png │ ├── login-req-process.png │ ├── other-dist=chart.png │ ├── other-result-page.png │ ├── other-total-chart.png │ ├── data-module-static.png │ ├── entire-arch-dynamic.png │ ├── req-handler-process.png │ └── web-basic-module-static.png ├── test │ ├── knn.txt │ ├── nb.txt │ ├── svm.txt │ ├── kmeans.txt │ └── kmedoids.txt └── diag │ ├── entire-arch-0.fem │ └── traditional-mvc-0.fem ├── dm ├── __init__.py ├── datasets.py ├── clusterBase.py ├── k_medoids.py ├── preprocess.py └── apriori.py ├── config.py ├── init ├── init.sql ├── init_db.py ├── init_rmp_iris.py ├── init_rmp_iris2.py └── init_rmp_cart.py ├── update.js ├── index.py ├── rmp_simulator.py └── req_handlers.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /app.wsgi: -------------------------------------------------------------------------------- 1 | from test import app as application -------------------------------------------------------------------------------- /page/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/img/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/db.png -------------------------------------------------------------------------------- /page/js/checklogin.js: -------------------------------------------------------------------------------- 1 | if(getUser()) //已登录 2 | location.href = './index.html'; -------------------------------------------------------------------------------- /doc/img/knn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/knn.png -------------------------------------------------------------------------------- /doc/img/pages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/pages.png -------------------------------------------------------------------------------- /doc/test/knn.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/test/knn.txt -------------------------------------------------------------------------------- /doc/test/nb.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/test/nb.txt -------------------------------------------------------------------------------- /doc/test/svm.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/test/svm.txt -------------------------------------------------------------------------------- /page/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/page/img/bg.png -------------------------------------------------------------------------------- /page/js/checknotlogin.js: -------------------------------------------------------------------------------- 1 | if(!getUser()) //已登录 2 | location.href = './login.html'; -------------------------------------------------------------------------------- /doc/img/apriori.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/apriori.jpg -------------------------------------------------------------------------------- /doc/img/dm-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/dm-page.png -------------------------------------------------------------------------------- /doc/img/graham.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/graham.png -------------------------------------------------------------------------------- /doc/img/kmeans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/kmeans.png -------------------------------------------------------------------------------- /doc/test/kmeans.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/test/kmeans.txt -------------------------------------------------------------------------------- /doc/img/assoc-csv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/assoc-csv.png -------------------------------------------------------------------------------- /doc/img/assoc-dist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/assoc-dist.png -------------------------------------------------------------------------------- /doc/img/dm-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/dm-process.png -------------------------------------------------------------------------------- /doc/img/dm-top-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/dm-top-10.png -------------------------------------------------------------------------------- /doc/img/dv-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/dv-process.png -------------------------------------------------------------------------------- /doc/img/getCookie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/getCookie.png -------------------------------------------------------------------------------- /doc/img/gramham-eg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/gramham-eg.gif -------------------------------------------------------------------------------- /doc/img/kmedoids.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/kmedoids.png -------------------------------------------------------------------------------- /doc/img/orm-static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/orm-static.png -------------------------------------------------------------------------------- /doc/img/other-csv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/other-csv.png -------------------------------------------------------------------------------- /doc/img/other-dist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/other-dist.png -------------------------------------------------------------------------------- /doc/img/pages-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/pages-arch.png -------------------------------------------------------------------------------- /doc/img/rmp-model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/rmp-model.png -------------------------------------------------------------------------------- /doc/img/rsrc-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/rsrc-page.png -------------------------------------------------------------------------------- /doc/img/use-case.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/use-case.png -------------------------------------------------------------------------------- /doc/test/kmedoids.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/test/kmedoids.txt -------------------------------------------------------------------------------- /page/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/page/img/loading.gif -------------------------------------------------------------------------------- /doc/img/algo-module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/algo-module.png -------------------------------------------------------------------------------- /doc/img/apriori-impl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/apriori-impl.png -------------------------------------------------------------------------------- /doc/img/assoc-total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/assoc-total.png -------------------------------------------------------------------------------- /doc/img/entire-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/entire-arch.png -------------------------------------------------------------------------------- /doc/img/history-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/history-page.png -------------------------------------------------------------------------------- /doc/img/kmeoids-ompl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/kmeoids-ompl.png -------------------------------------------------------------------------------- /doc/img/message-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/message-page.png -------------------------------------------------------------------------------- /doc/img/other-total.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/other-total.png -------------------------------------------------------------------------------- /doc/img/project-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/project-page.png -------------------------------------------------------------------------------- /doc/img/seperate-mvc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/seperate-mvc.png -------------------------------------------------------------------------------- /doc/img/setting-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/setting-page.png -------------------------------------------------------------------------------- /doc/img/dm-req-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/dm-req-process.png -------------------------------------------------------------------------------- /doc/img/rmp-comp-rsrc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/rmp-comp-rsrc.png -------------------------------------------------------------------------------- /doc/img/rmp-single-rsrc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/rmp-single-rsrc.png -------------------------------------------------------------------------------- /doc/img/toolkit-archi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/toolkit-archi.png -------------------------------------------------------------------------------- /doc/img/traditional-mvc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/traditional-mvc.png -------------------------------------------------------------------------------- /doc/img/assoc-dist-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/assoc-dist-chart.png -------------------------------------------------------------------------------- /doc/img/assoc-result-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/assoc-result-page.png -------------------------------------------------------------------------------- /doc/img/assoc-total-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/assoc-total-chart.png -------------------------------------------------------------------------------- /doc/img/front-end-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/front-end-process.png -------------------------------------------------------------------------------- /doc/img/login-req-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/login-req-process.png -------------------------------------------------------------------------------- /doc/img/other-dist=chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/other-dist=chart.png -------------------------------------------------------------------------------- /doc/img/other-result-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/other-result-page.png -------------------------------------------------------------------------------- /doc/img/other-total-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/other-total-chart.png -------------------------------------------------------------------------------- /doc/img/data-module-static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/data-module-static.png -------------------------------------------------------------------------------- /doc/img/entire-arch-dynamic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/entire-arch-dynamic.png -------------------------------------------------------------------------------- /doc/img/req-handler-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/req-handler-process.png -------------------------------------------------------------------------------- /doc/img/web-basic-module-static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizardforcel/bs092/HEAD/doc/img/web-basic-module-static.png -------------------------------------------------------------------------------- /dm/__init__.py: -------------------------------------------------------------------------------- 1 | from k_medoids import kmedoids 2 | from apriori import apriori 3 | from preprocess import * 4 | from datasets import * 5 | -------------------------------------------------------------------------------- /page/logout.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dm/datasets.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | def loadCart(): 4 | return [ 5 | [ '豆奶', '莴苣' , '', ''], 6 | [ '莴苣', '尿布', '葡萄酒', '甜菜' ], 7 | [ '莴苣', '尿布', '葡萄酒', '橙汁' ], 8 | [ '莴苣', '豆奶', '尿布', '葡萄酒' ], 9 | [ '莴苣', '豆奶', '尿布', '橙汁' ] 10 | ] -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import MySQLdb 2 | import os 3 | 4 | host = 'http://localhost:5000' 5 | 6 | db = { 7 | 'host': '127.0.0.1', 8 | 'username': 'root', 9 | 'password': '123456', 10 | 'port': 3306, 11 | 'name': 'test' 12 | } 13 | 14 | smtp = { 15 | 'server': 'smtp.qq.com', 16 | 'un': 'wizard.z@qq.com', 17 | 'authcode': 'juganzlzmlfhbdja' 18 | } 19 | 20 | rmp = 'http://202.120.40.73:28080' 21 | #rmp = 'http://localhost:5000' 22 | 23 | staticPath = 'page' 24 | 25 | def getConn(): 26 | return MySQLdb.connect(host=db["host"], \ 27 | user=db["username"], \ 28 | passwd=db["password"], \ 29 | port=db["port"], \ 30 | db=db["name"], \ 31 | charset="utf8") -------------------------------------------------------------------------------- /init/init.sql: -------------------------------------------------------------------------------- 1 | create table history 2 | ( 3 | id int primary key auto_increment, 4 | userid varchar(16), 5 | proj varchar(32), 6 | rsrc varchar(32), 7 | tp varchar(16), 8 | tm timestamp 9 | ) DEFAULT CHARSET=utf8 10 | 11 | create table result 12 | ( 13 | hid int, 14 | id varchar(32), 15 | res1 varchar(16), 16 | res2 varchar(256), 17 | res3 varchar(16), 18 | res4 varchar(16), 19 | primary key(hid, id), 20 | foreign key(hid) references history(id) 21 | ) DEFAULT CHARSET=utf8 22 | 23 | create table message 24 | ( 25 | id int primary key auto_increment, 26 | userid varchar(16), 27 | content varchar(64), 28 | tm timestamp, 29 | isread tinyint default 0 30 | ) DEFAULT CHARSET=utf8 31 | 32 | create table email 33 | ( 34 | userid varchar(16) primary key, 35 | email varchar(32) 36 | )DEFAULT CHARSET=utf8 -------------------------------------------------------------------------------- /init/init_db.py: -------------------------------------------------------------------------------- 1 | from sklearn import datasets 2 | from sklearn.cluster import KMeans, MiniBatchKMeans 3 | import MySQLdb 4 | iris = datasets.load_iris() 5 | #digits = datasets.load_digits() 6 | #print type(iris.data), iris.data.shape 7 | #print iris.target 8 | 9 | """ 10 | conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='123456',db="test") 11 | cur = conn.cursor() 12 | 13 | for i in range(len(iris.data)): 14 | elem = iris.data[i]; 15 | sql = "insert into iris values (%s, %s, %s, %s, %s)" 16 | cur.execute(sql, (i, elem[0], elem[1], elem[2], elem[3])) 17 | 18 | conn.commit() 19 | cur.close() 20 | conn.close() 21 | """ 22 | 23 | clf = KMeans(n_clusters=9) 24 | clf.fit(iris.data) 25 | print clf,"\n", clf.labels_,"\n", clf.cluster_centers_ 26 | 27 | """ 28 | clf = MiniBatchKMeans(n_clusters=9) 29 | clf.fit(iris.data) 30 | print clf,"\n", clf.labels_,"\n", clf.cluster_centers_ 31 | """ -------------------------------------------------------------------------------- /init/init_rmp_iris.py: -------------------------------------------------------------------------------- 1 | from sklearn import datasets 2 | import urllib2 3 | import json 4 | iris = datasets.load_iris() 5 | 6 | headers = { 7 | 'Content-Type': 'application/json', 8 | 'passwd': '123456' 9 | } 10 | url = 'http://202.120.40.73:28080/Entity/U7f2d2f8faaa9/test/Iris/?userid=233837063867287' 11 | 12 | 13 | #r = [] 14 | for row in iris.data: 15 | elem = { 16 | "col0": int(row[0] * 10) / 10.0, 17 | "col1": int(row[1] * 10) / 10.0, 18 | "col2": int(row[2] * 10) / 10.0, 19 | "col3": int(row[3] * 10) / 10.0 20 | } 21 | #r.append(elem) 22 | postStr = json.dumps(elem) 23 | req = urllib2.Request(url, postStr, headers) 24 | res = urllib2.urlopen(req) 25 | print res.read().decode('utf-8') 26 | #postStr = json.dumps(r) 27 | 28 | """ 29 | req = urllib2.Request(url, postStr, headers) 30 | res = urllib2.urlopen(req) 31 | print res.read().decode('utf-8') 32 | """ -------------------------------------------------------------------------------- /init/init_rmp_iris2.py: -------------------------------------------------------------------------------- 1 | from sklearn import datasets 2 | import urllib2 3 | import json 4 | iris = datasets.load_iris() 5 | 6 | headers = { 7 | 'Content-Type': 'application/json', 8 | 'passwd': '123456' 9 | } 10 | url = 'http://202.120.40.73:28080/Entity/U7f2d2f8faaa9/test/Iris2/?userid=233837063867287' 11 | 12 | 13 | #r = [] 14 | i = 0 15 | for row in iris.data: 16 | elem = { 17 | "col0": int(row[0] * 10) / 10.0, 18 | "col1": int(row[1] * 10) / 10.0, 19 | "col2": int(row[2] * 10) / 10.0, 20 | "col3": int(row[3] * 10) / 10.0, 21 | "label": iris.target[i] 22 | } 23 | #r.append(elem) 24 | postStr = json.dumps(elem) 25 | req = urllib2.Request(url, postStr, headers) 26 | res = urllib2.urlopen(req) 27 | print res.read().decode('utf-8') 28 | i += 1 29 | #postStr = json.dumps(r) 30 | 31 | """ 32 | req = urllib2.Request(url, postStr, headers) 33 | res = urllib2.urlopen(req) 34 | print res.read().decode('utf-8') 35 | """ -------------------------------------------------------------------------------- /update.js: -------------------------------------------------------------------------------- 1 | var process = require('child_process'); 2 | 3 | var getTimeStr = function() { 4 | 5 | var tm = new Date(); 6 | var o = { 7 | yr: tm.getFullYear(), 8 | mon: tm.getMonth() + 1, 9 | dt: tm.getDate(), 10 | hr: tm.getHours(), 11 | min: tm.getMinutes(), 12 | sec: tm.getSeconds() 13 | }; 14 | for(var i in o) 15 | { 16 | o[i] = o[i].toString(); 17 | if(o[i].length < 2) 18 | o[i] = '0' + o[i]; 19 | } 20 | return o.yr + '-' + o.mon + '-' + o.dt + 21 | ' ' + o.hr + ':' + o.min + ':' + o.sec; 22 | }; 23 | 24 | var cmds = [ 25 | 'git add -A', 26 | 'git commit -m "' + getTimeStr() + '"', 27 | 'git push', 28 | 'git push github master' 29 | ]; 30 | 31 | for(var cmd of cmds) { 32 | try { 33 | console.log(cmd); 34 | console.log(process.execSync(cmd).toString()); 35 | } catch(ex) { 36 | console.log(ex.toString()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /init/init_rmp_cart.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from sklearn import datasets 4 | import urllib2 5 | import json 6 | iris = datasets.load_iris() 7 | 8 | headers = { 9 | 'Content-Type': 'application/json', 10 | 'passwd': '123456' 11 | } 12 | url = 'http://202.120.40.73:28080/Entity/U7f2d2f8faaa9/test/Cart/?userid=233837063867287' 13 | 14 | 15 | dataset = [ 16 | [ '豆奶', '莴苣' , '', ''], 17 | [ '莴苣', '尿布', '葡萄酒', '甜菜' ], 18 | [ '莴苣', '尿布', '葡萄酒', '橙汁' ], 19 | [ '莴苣', '豆奶', '尿布', '葡萄酒' ], 20 | [ '莴苣', '豆奶', '尿布', '橙汁' ] 21 | ] 22 | 23 | #r = [] 24 | for row in dataset: 25 | elem = { 26 | "col0": row[0], 27 | "col1": row[1], 28 | "col2": row[2], 29 | "col3": row[3] 30 | } 31 | #r.append(elem) 32 | postStr = json.dumps(elem) 33 | req = urllib2.Request(url, postStr, headers) 34 | res = urllib2.urlopen(req) 35 | print res.read().decode('utf-8') 36 | #postStr = json.dumps(r) 37 | 38 | """ 39 | req = urllib2.Request(url, postStr, headers) 40 | res = urllib2.urlopen(req) 41 | print res.read().decode('utf-8') 42 | """ -------------------------------------------------------------------------------- /page/js/login.js: -------------------------------------------------------------------------------- 1 | $(function() 2 | { 3 | var doLogin = function() 4 | { 5 | var un = $('#un-txt').val(); 6 | var pw = $('#pw-txt').val(); 7 | if(!un || !pw) 8 | { 9 | alert('用户名和密码不能为空!'); 10 | return; 11 | } 12 | 13 | var url = getUrl(); 14 | 15 | $.ajax({ 16 | type: "GET", 17 | url: url + "/System/User?username=" + un + "&passwd=" + pw, 18 | dataType: "json", 19 | beforeSend: function (request) { 20 | request.setRequestHeader("passwd", pw); 21 | } 22 | }).done(function (data) { 23 | if (data.error != null) { 24 | alert("登录失败!\n\nError: " + data.error.message); 25 | return; 26 | } 27 | setUser(data.id, un, pw); 28 | location.href = './index.html'; 29 | }).fail(function (XMLHttpRequest, textStatus, errorThrown) { 30 | alert('登录失败!\n\n' + textStatus + ": " + errorThrown); 31 | }); 32 | }; 33 | 34 | $('#lgn-btn').click(doLogin); 35 | }); -------------------------------------------------------------------------------- /dm/clusterBase.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | def importData(FIFE = 'blogdata.txt') : 4 | blogwords = [] 5 | blognames = [] 6 | f = open(FIFE, 'r') 7 | words = f.readline().split() 8 | #//remove '\r\n' 9 | for line in f: 10 | blog = line[:-2].split('\t') 11 | blognames.append(blog[0]) 12 | blogwords.append([int(word_c) for word_c in blog[1:]] ) 13 | return blogwords,blognames 14 | 15 | 16 | def pearson_distance(vector1, vector2) : 17 | """ 18 | Calculate distance between two vectors using pearson method 19 | See more : http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient 20 | """ 21 | sum1 = sum(vector1) 22 | sum2 = sum(vector2) 23 | 24 | sum1Sq = sum([pow(v,2) for v in vector1]) 25 | sum2Sq = sum([pow(v,2) for v in vector2]) 26 | 27 | pSum = sum([vector1[i] * vector2[i] for i in range(len(vector1))]) 28 | 29 | num = pSum - (sum1*sum2/len(vector1)) 30 | den = sqrt((sum1Sq - pow(sum1,2)/len(vector1)) * (sum2Sq - pow(sum2,2)/len(vector1))) 31 | 32 | if den == 0 : return 0.0 33 | return 1.0 - num/den -------------------------------------------------------------------------------- /page/js/reg.js: -------------------------------------------------------------------------------- 1 | $(function() 2 | { 3 | var doReg = function() 4 | { 5 | var un = $('#un-txt').val(); 6 | var pw = $('#pw-txt').val(); 7 | var pw2 = $('#pw2-txt').val(); 8 | if(!un || !pw) 9 | { 10 | alert('用户名和密码不能为空!'); 11 | return; 12 | } 13 | if(pw != pw2) 14 | { 15 | alert('两次输入密码不一致!'); 16 | return; 17 | } 18 | 19 | var url = getUrl(); 20 | 21 | $.ajax({ 22 | type: "POST", 23 | url: url + "/System/User", 24 | dataType: "json", 25 | contentType: "application/json", 26 | data: JSON.stringify({username: un, passwd: pw}), 27 | beforeSend: function (request) { 28 | request.setRequestHeader("passwd", pw); 29 | } 30 | }).done(function (data) { 31 | if (data.error != null) { 32 | alert("登录失败!\n\nError: " + data.error.message); 33 | return; 34 | } 35 | setUser(data.message, un, pw); 36 | location.href = './index.html'; 37 | }).fail(function (XMLHttpRequest, textStatus, errorThrown) { 38 | alert('注册失败!\n\n' + textStatus + ": " + errorThrown); 39 | }); 40 | }; 41 | 42 | $('#reg-btn').click(doReg); 43 | }); -------------------------------------------------------------------------------- /page/js/common.js: -------------------------------------------------------------------------------- 1 | $(function() 2 | { 3 | var user = getUser(); 4 | 5 | if(user) 6 | { 7 | $('.navbar-nav').append('
  • 项目
  • '); 8 | $('.navbar-nav').append('
  • 历史
  • '); 9 | $('.navbar-nav').append(''); 10 | $('.navbar-nav').append('
  • 设置
  • '); 11 | $('.navbar-nav').append('
  • 返回主站
  • '); 12 | $('.navbar-nav').append('
  • 退出
  • '); 13 | } 14 | else 15 | { 16 | $('.navbar-nav').append('
  • 登录
  • '); 17 | $('.navbar-nav').append('
  • 注册
  • '); 18 | } 19 | 20 | 21 | var getNotify = function() { 22 | $.ajax({ 23 | type: "GET", 24 | url: "notify/" + user.id + '/', 25 | dataType: "json" 26 | }).done(function(json) { 27 | if (!json.succ) 28 | alert(json.errmsg); 29 | else { 30 | if(json.unread != 0) { 31 | $('#nav-msg .badge').remove(); 32 | var $badge = $('' + json.unread + ''); 33 | $('#nav-msg a').append($badge); 34 | } 35 | } 36 | }).fail(function(data) { 37 | console.log('Get notify failed!'); 38 | }); 39 | } 40 | 41 | if(user) { 42 | getNotify(); 43 | setInterval(getNotify, 1 * 60 * 1000); 44 | } 45 | }); -------------------------------------------------------------------------------- /page/js/setting.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var uid = localStorage['id']; 4 | 5 | var getEmail = function() { 6 | 7 | $('#modal-loading').modal('show'); 8 | $.ajax({ 9 | type: "GET", 10 | url: 'email/' + uid, 11 | dataType: "json" 12 | }).done(function(json) { 13 | if (!json.succ) 14 | alert(json.errmsg); 15 | else 16 | $('#email-txt').val(json.data); 17 | $('#modal-loading').modal('hide'); 18 | }).fail(function(data) { 19 | alert('Network error!'); 20 | $('#modal-loading').modal('hide'); 21 | }); 22 | 23 | }; 24 | 25 | var setEmail = function() { 26 | var $emailTxt = $('#email-txt'); 27 | if(!$emailTxt[0].checkValidity()) 28 | { 29 | alert('邮箱格式错误!'); 30 | return; 31 | } 32 | 33 | var email = $emailTxt.val(); 34 | 35 | $.ajax({ 36 | type: "POST", 37 | url: 'email/' + uid + '/update/', 38 | data: 'email=' + email, 39 | contentType: "application/x-www-form-urlencoded", 40 | dataType: "json" 41 | }).done(function(json) { 42 | if (!json.succ) 43 | alert(json.errmsg); 44 | else 45 | alert('设置成功!'); 46 | $('#modal-loading').modal('hide'); 47 | }).fail(function(data) { 48 | alert('Network error!'); 49 | $('#modal-loading').modal('hide'); 50 | }); 51 | }; 52 | $('#email-btn').click(setEmail); 53 | 54 | getEmail(); 55 | }); -------------------------------------------------------------------------------- /page/css/main.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | margin-top: 15px; 3 | } 4 | 5 | .well, .navbar { 6 | border: 1px solid rgba(0, 0, 0, 0.2); 7 | } 8 | 9 | * { font-family: "Microsoft YaHei"; } 10 | 11 | @media (min-width: 1500px) { 12 | .container { 13 | width: 1470px; 14 | } 15 | } 16 | 17 | body { 18 | background-image: url(/img/bg.png); 19 | } 20 | 21 | .col-md-1, 22 | .col-md-2, 23 | .col-md-3, 24 | .col-md-4, 25 | .col-md-5, 26 | .col-md-6 27 | { 28 | padding-top: 5px; 29 | padding-bottom: 5px; 30 | } 31 | 32 | .pag-num { 33 | 34 | } 35 | 36 | .pag-next { 37 | float: right; 38 | } 39 | 40 | .pag-prev { 41 | float: left; 42 | } 43 | 44 | #pag-bar { 45 | text-align: center; 46 | border: 1px solid #337ab7; 47 | border-radius: 4px; 48 | border-top-left-radius: 0; 49 | border-top-right-radius: 0; 50 | background-color: #337ab7; 51 | padding: 0; 52 | } 53 | 54 | #pag-bar .btn { 55 | border: 0; 56 | } 57 | 58 | .axis path, 59 | .axis line{ 60 | fill: none; 61 | stroke: black; 62 | /*shape-rendering: crispEdges;*/ 63 | } 64 | 65 | .axis text { 66 | font-family: sans-serif; 67 | font-size: 11px; 68 | } 69 | 70 | .form-label { 71 | height: 34px; 72 | padding: 6px 12px; 73 | margin: 0; 74 | } 75 | 76 | .msg-mark { 77 | float: right; 78 | font-size: 80%; 79 | vertical-align: middle; 80 | } 81 | 82 | .msg-tm { 83 | float: right; 84 | font-size: 80%; 85 | vertical-align: middle; 86 | margin-right: 10px; 87 | } 88 | 89 | .msg-read { 90 | background: #fff; 91 | } 92 | 93 | #nav-msg .badge { 94 | margin-left: 5px; 95 | } 96 | 97 | .footer { 98 | margin-top: 20px; 99 | padding-top: 20px; 100 | border-top: 1px solid #ccc; 101 | } 102 | 103 | .panel, .well { 104 | box-shadow: inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075); 105 | } -------------------------------------------------------------------------------- /page/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 23 | 24 | 25 |
    26 | 27 | 42 | 43 |
    44 |
    45 |

    登录

    46 |
    47 |
    48 | 49 | 50 | 51 |
    52 |
    53 | 54 | 57 |
    58 | 59 | -------------------------------------------------------------------------------- /page/reg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 23 | 24 | 25 |
    26 | 27 | 42 | 43 |
    44 |
    45 |

    注册

    46 |
    47 |
    48 | 49 | 50 | 51 | 52 |
    53 |
    54 | 55 | 58 |
    59 | 60 | -------------------------------------------------------------------------------- /page/message.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | 33 | 34 |
    35 | 36 |
    37 | 38 | 41 |
    42 | 43 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /index.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from flask import Flask, send_from_directory, redirect 4 | import req_handlers 5 | import rmp_simulator 6 | import config 7 | import os 8 | 9 | app = Flask(__name__) 10 | app.debug = True 11 | 12 | app.add_url_rule('/System/User/', view_func=rmp_simulator.login) 13 | app.add_url_rule('/System/Project/', view_func=rmp_simulator.getProj) 14 | app.add_url_rule('/System/Resource/', view_func=rmp_simulator.getRsrc) 15 | app.add_url_rule('/System/Resource/list/', view_func=rmp_simulator.getRsrcList) 16 | app.add_url_rule('/Entity///Iris/', view_func=rmp_simulator.iris) 17 | app.add_url_rule('/Entity///Cart/', view_func=rmp_simulator.cart) 18 | 19 | app.add_url_rule('/mining/////', view_func=req_handlers.mining, methods=['POST']) 20 | app.add_url_rule('/history//', view_func=req_handlers.getHistory) 21 | app.add_url_rule('/history///', view_func=req_handlers.getHistoryById) 22 | app.add_url_rule('/result//', view_func=req_handlers.getResultById) 23 | app.add_url_rule('/result//csv/', view_func=req_handlers.getResultCsv) 24 | app.add_url_rule('/message//', view_func=req_handlers.getMessageUnread) 25 | app.add_url_rule('/message//all/', view_func=req_handlers.getMessageAll) 26 | app.add_url_rule('/message//mark//', view_func=req_handlers.markMessage) 27 | app.add_url_rule('/message//mark/all/', view_func=req_handlers.markMessageAll) 28 | app.add_url_rule('/notify//', view_func=req_handlers.notify) 29 | app.add_url_rule('/email//', view_func=req_handlers.getEmail) 30 | app.add_url_rule('/email//update/', view_func=req_handlers.setEmail, methods=['POST']) 31 | 32 | @app.route('/') 33 | def staticHtml(path): 34 | return send_from_directory(config.staticPath, path) 35 | 36 | @app.route('/js/') 37 | def staticJs(path): 38 | return send_from_directory(os.path.join(config.staticPath, 'js'), path) 39 | 40 | @app.route('/css/') 41 | def staticCss(path): 42 | return send_from_directory(os.path.join(config.staticPath, 'css'), path) 43 | 44 | @app.route('/img/') 45 | def staticImg(path): 46 | return send_from_directory(os.path.join(config.staticPath, 'img'), path) 47 | 48 | @app.route('/') 49 | def redirIndex(): 50 | return redirect('/index.html') 51 | 52 | if __name__ == '__main__': 53 | app.run(threaded=True) -------------------------------------------------------------------------------- /page/js/project.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | var user = getUser(); 4 | var url = getUrl() + "/System/Project?userid=" + user.id; 5 | 6 | 7 | 8 | var getProj = function() 9 | { 10 | $('#modal-loading').modal('show'); 11 | 12 | $.ajax({ 13 | type: "GET", 14 | url: url, 15 | dataType: "xml", 16 | beforeSend: function (request) { 17 | request.setRequestHeader("passwd", user.pw); 18 | } 19 | }).done(function(data) { 20 | var $data = $(data); 21 | var errmsg = $data.find("error").text(); 22 | if (errmsg !== "") 23 | alert(errmsg); 24 | else 25 | loadProj($data.find('project')); 26 | $('#modal-loading').modal('hide'); 27 | }).fail(function(data) { 28 | alert('Network error!'); 29 | $('#modal-loading').modal('hide'); 30 | }); 31 | }; 32 | 33 | var loadProj = function($list) 34 | { 35 | tmStr = getTimeStr(); 36 | $('.proj-row').remove(); 37 | for(var i = 0; i < $list.length; i++) 38 | { 39 | var $elem = $list.eq(i); 40 | var name = $elem.find('name').text(); 41 | var tmp = name.split("/", 2); 42 | localStorage.setItem('token', tmp[0]); 43 | name = tmp[1]; 44 | var time = $elem.find('time').text() || tmStr; 45 | var status = parseInt($elem.find("privilege").text()); 46 | status = statusMap[status]; 47 | 48 | var $tr = $(''); 49 | var $nameTd = $('' + name + ''); 50 | var $timeTd = $('' + time + ''); 51 | var $statusTd = $('' + status + ''); 52 | var $opTd = $(''); 53 | var $viewAnchor = $('查看'); 54 | $opTd.append($viewAnchor); 55 | $tr.append($nameTd); 56 | $tr.append($timeTd); 57 | $tr.append($statusTd); 58 | $tr.append($opTd); 59 | $('#proj-table').append($tr); 60 | } 61 | $('.proj-view').click(viewProj); 62 | }; 63 | 64 | var viewProj = function() { 65 | event.preventDefault(); 66 | var proj = $(this).parent().parent().children('.proj-name').text(); 67 | localStorage.setItem('proj', proj); 68 | location.href = './rsrc.html'; 69 | }; 70 | 71 | getProj(); 72 | }); -------------------------------------------------------------------------------- /page/rsrc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 32 | 33 |
    34 |
    35 |

    36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
    名称状态最后修改操作
    45 |
    46 | 47 |
    48 |

    Copyright © 2016 IST LAB

    49 |
    50 |
    51 | 52 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /page/project.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 32 | 33 |
    34 |
    35 |

    项目列表

    36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
    名称时间状态操作
    45 |
    46 | 47 |
    48 |

    Copyright © 2016 IST LAB

    49 |
    50 | 51 |
    52 | 53 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /page/history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 32 | 33 |
    34 |
    35 |

    历史

    36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
    标题资源类型时间操作
    46 |
    47 | 48 |
    49 |

    Copyright © 2016 IST LAB

    50 |
    51 |
    52 | 53 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /page/setting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 32 | 33 |
    34 |
    35 |

    邮箱

    36 |
    37 |
    38 |
    39 |
    40 |

    邮箱

    41 |
    42 |
    43 | 44 |
    45 |
    46 | 47 |
    48 |
    49 |
    50 |
    51 | 52 |
    53 |

    Copyright © 2016 IST LAB

    54 |
    55 | 56 |
    57 | 58 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /page/js/history.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | var uid = localStorage['id']; 4 | 5 | var getHistory = function() { 6 | $('#modal-loading').modal('show'); 7 | $.ajax({ 8 | type: "GET", 9 | url: "history/" + uid + '/', 10 | dataType: "json" 11 | }).done(function(json) { 12 | if (!json.succ) 13 | alert(json.errmsg); 14 | else 15 | loadHistory(json.data); 16 | $('#modal-loading').modal('hide'); 17 | }).fail(function(data) { 18 | alert('Network error!'); 19 | $('#modal-loading').modal('hide'); 20 | }); 21 | }; 22 | 23 | 24 | var loadHistory = function(list) { 25 | 26 | $('.history-row').remove(); 27 | 28 | for(var i = 0; i < list.length; i++) 29 | { 30 | var elem = list[i]; 31 | var url = getUrl() + '/Entity/' + elem.rsrc + '/'; 32 | 33 | var $tr = $(''); 34 | $tr.attr('data-id', elem.id); 35 | var $titleTd = $('' + (elem.title || elem.id) + ''); 36 | var $rsrcTd = $('' + elem.rsrc + ''); 37 | var $typeTd = $('' + algoDict[elem.type] + ''); 38 | var $timeTd = $('' + elem.time + ''); 39 | var $opTd = $(''); 40 | var $viewAnchor = $('查看'); 41 | var $csvAnchor = $('导出'); 42 | 43 | $opTd.append($viewAnchor); 44 | $opTd.append(' '); 45 | $opTd.append($csvAnchor); 46 | $tr.append($titleTd); 47 | $tr.append($rsrcTd); 48 | $tr.append($typeTd); 49 | $tr.append($timeTd); 50 | $tr.append($opTd); 51 | $('#history-table').append($tr); 52 | } 53 | 54 | $('.view-result').click(viewResult); 55 | redirToResult(location.hash.slice(1)); 56 | } 57 | 58 | var viewResult = function() { 59 | event.preventDefault(); 60 | var id = $(this).parent().parent().attr('data-id'); 61 | var rsrc = $(this).parent().parent().children('.history-rsrc').text(); 62 | var type = $(this).parent().parent().children('.history-type').attr('data-type'); 63 | localStorage.setItem('resultId', id); 64 | localStorage.setItem('resultRsrc', rsrc); 65 | localStorage.setItem('resultType', type); 66 | location.href = './result.html'; 67 | } 68 | 69 | var redirToResult = function(id) { 70 | if(!id) return; 71 | var $li = $('.history-row'); 72 | for(var i = 0; i < $li.length; i++) { 73 | $row = $li.eq(i); 74 | if($row.attr('data-id') == id) 75 | $row.find('.view-result').click(); 76 | } 77 | }; 78 | 79 | getHistory(); 80 | }); -------------------------------------------------------------------------------- /page/js/rsrc.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var getRsrc = function() { 4 | 5 | $('#modal-loading').modal('show'); 6 | var proj = localStorage.getItem('proj'); 7 | var token = localStorage.getItem('token'); 8 | $('#proj-name').text(proj); 9 | 10 | var user = getUser(); 11 | var url = getUrl() + "/System/Resource/list?userid=" + user.id + "&project=" + token + '/' + proj; 12 | $.ajax({ 13 | type: "GET", 14 | url: url, 15 | dataType: "xml", 16 | beforeSend: function (request) { 17 | request.setRequestHeader("passwd", user.pw); 18 | } 19 | }).done(function(data){ 20 | var $data = $(data); 21 | var errmsg = $data.find("error").text(); 22 | if (errmsg.length !== 0) 23 | alert(errmsg); 24 | else 25 | loadRsrc($(data).find("resource")); 26 | $('#modal-loading').modal('hide'); 27 | }).fail(function(data, status, e){ 28 | alert("network error"); 29 | $('#modal-loading').modal('hide'); 30 | }); 31 | }; 32 | 33 | var loadRsrc = function($list) { 34 | $('.rsrc-row').remove(); 35 | for(var i = 0; i < $list.length; i++) 36 | { 37 | var $item = $list.eq(i); 38 | var name = $item.children('name').text(); 39 | var status = $item.children('state').text(); 40 | status = (status == 'loaded')? '√': '×'; 41 | var lastModified = $item.children('lastmodified').text(); 42 | 43 | var $tr = $(''); 44 | var $nameTd = $('' + name + ''); 45 | var $statusTd = $('' + status + ''); 46 | var $lastTd = $('' + lastModified + ''); 47 | var $opTd = $(''); 48 | var $viewAnchor = $('查看'); 49 | var $mineAnchor = $('挖掘'); 50 | $opTd.append($viewAnchor); 51 | $opTd.append(' '); 52 | $opTd.append($mineAnchor); 53 | $tr.append($nameTd); 54 | $tr.append($statusTd); 55 | $tr.append($lastTd); 56 | $tr.append($opTd); 57 | $('#rsrc-table').append($tr); 58 | } 59 | $('.rsrc-view').click(viewRsrc); 60 | $('.rsrc-mine').click(mineRsrc); 61 | }; 62 | 63 | 64 | var viewRsrc = function() { 65 | event.preventDefault() 66 | var token = localStorage.getItem('token'); 67 | var proj = localStorage.getItem('proj'); 68 | var rsrc = $(this).parent().parent().children('.rsrc-name').text(); 69 | window.open(getUrl() + '/Entity/' + token + '/' + proj + '/' + rsrc + '/') 70 | }; 71 | 72 | var mineRsrc = function() { 73 | event.preventDefault() 74 | var rsrc = $(this).parent().parent().children('.rsrc-name').text(); 75 | localStorage.setItem('rsrc', rsrc); 76 | location.href = './mining.html'; 77 | }; 78 | 79 | getRsrc(); 80 | }); -------------------------------------------------------------------------------- /page/js/message.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var uid = localStorage['id']; 4 | 5 | var getMessage = function(all) { 6 | 7 | $('#modal-loading').modal('show'); 8 | var url = "message/" + uid + '/'; 9 | if(all) url += 'all/'; 10 | 11 | $.ajax({ 12 | type: "GET", 13 | url: url, 14 | dataType: "json" 15 | }).done(function(json) { 16 | if (!json.succ) 17 | alert(json.errmsg); 18 | else 19 | loadMessage(json.data); 20 | $('#modal-loading').modal('hide'); 21 | }).fail(function(data) { 22 | alert('Network error!'); 23 | $('#modal-loading').modal('hide'); 24 | }); 25 | }; 26 | 27 | var loadMessage = function(list) { 28 | if(list.length == 0) { 29 | $('#msg-li').append('
    您目前没有任何消息
    '); 30 | return; 31 | } 32 | 33 | $('.msg-well').remove(); 34 | for(var i = 0; i < list.length; i++) { 35 | var elem = list[i]; 36 | var hid = /ID:(\d+)/.exec(elem.content)[1]; 37 | 38 | var $well = $('
    '); 39 | $well.attr('data-id', elem.id); 40 | if(elem.isread) $well.addClass('msg-read'); 41 | $link = $(''); 42 | $link.text(elem.content); 43 | $well.append($link); 44 | 45 | if(!elem.isread) { 46 | $markSpan = $('标记已读') 47 | $well.append($markSpan); 48 | } 49 | 50 | $tmSpan = $(''); 51 | $tmSpan.text(elem.tm); 52 | $well.append($tmSpan); 53 | 54 | $('#msg-li').append($well); 55 | } 56 | $('.msg-mark').click(markRead); 57 | //$('.msg-link').click(viewResult); 58 | }; 59 | 60 | var markRead = function() { 61 | event.preventDefault(); 62 | var $well = $(this).parent() 63 | var id = $well.attr('data-id'); 64 | 65 | $.ajax({ 66 | type: "GET", 67 | url: 'message/' + uid + '/mark/' + id + '/', 68 | dataType: "json" 69 | }).done(function(json) { 70 | if (!json.succ) 71 | alert(json.errmsg); 72 | else { 73 | $well.fadeOut("normal",function(){this.remove()}); 74 | } 75 | }).fail(function(data) { 76 | alert('Network error!'); 77 | }); 78 | } 79 | 80 | /*var viewResult = function() { 81 | event.preventDefault(); 82 | id = /ID:(\d+)/.exec($(this).text())[1]; 83 | $.ajax({ 84 | type: "GET", 85 | url: "history/" + uid + '/' + id + '/', 86 | dataType: "json" 87 | }).done(function(json) { 88 | if (!json.succ) 89 | alert(json.errmsg); 90 | else { 91 | localStorage.setItem('resultId', id); 92 | localStorage.setItem('resultRsrc', json.data[0].rsrc); 93 | localStorage.setItem('resultType', json.data[0].type); 94 | location.href = './result.html'; 95 | } 96 | }).fail(function(data) { 97 | alert('Network error!'); 98 | }); 99 | }*/ 100 | 101 | getMessage(false); 102 | }); -------------------------------------------------------------------------------- /dm/k_medoids.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Another clusting method , k-medoids. 3 | See more : http://en.wikipedia.org/wiki/K-medoids 4 | The most common realisation of k-medoid clustering is the Partitioning Around Medoids (PAM) algorithm and is as follows:[2] 5 | 1. Initialize: randomly select k of the n data points as the medoids 6 | 2. Associate each data point to the closest medoid. ("closest" here is defined using any valid distance metric, most commonly Euclidean distance, Manhattan distance or Minkowski distance) 7 | 3. For each medoid m 8 | For each non-medoid data point o 9 | Swap m and o and compute the total cost of the configuration 10 | 4. Select the configuration with the lowest cost. 11 | 5. repeat steps 2 to 4 until there is no change in the medoid. 12 | ''' 13 | from clusterBase import importData, pearson_distance 14 | from sklearn import datasets 15 | import random 16 | 17 | iris = datasets.load_iris() 18 | 19 | distances_cache = {} 20 | 21 | def totalcost(blogwords, costf, medoids_idx) : 22 | size = len(blogwords) 23 | total_cost = 0.0 24 | medoids = {} 25 | for idx in medoids_idx : 26 | medoids[idx] = [] 27 | for i in range(size) : 28 | choice = None 29 | min_cost = 2.1 30 | for m in medoids : 31 | tmp = distances_cache.get((m,i),None) 32 | if tmp is None : 33 | tmp = pearson_distance(blogwords[m],blogwords[i]) 34 | distances_cache[(m,i)] = tmp 35 | if tmp < min_cost : 36 | choice = m 37 | min_cost = tmp 38 | medoids[choice].append(i) 39 | total_cost += min_cost 40 | return total_cost, medoids 41 | 42 | 43 | def kmedoids(blogwords, k=8) : 44 | size = len(blogwords) 45 | medoids_idx = random.sample([i for i in range(size)], k) 46 | pre_cost, medoids = totalcost(blogwords,pearson_distance,medoids_idx) 47 | print pre_cost 48 | current_cost = 2.1 * size # maxmum of pearson_distances is 2. 49 | best_choice = [] 50 | best_res = {} 51 | iter_count = 0 52 | while 1 : 53 | for m in medoids : 54 | for item in medoids[m] : 55 | if item != m : 56 | idx = medoids_idx.index(m) 57 | swap_temp = medoids_idx[idx] 58 | medoids_idx[idx] = item 59 | tmp,medoids_ = totalcost(blogwords,pearson_distance,medoids_idx) 60 | #print tmp,'-------->',medoids_.keys() 61 | if tmp < current_cost : 62 | best_choice = list(medoids_idx) 63 | best_res = dict(medoids_) 64 | current_cost = tmp 65 | medoids_idx[idx] = swap_temp 66 | iter_count += 1 67 | print current_cost,iter_count 68 | if best_choice == medoids_idx : break 69 | if current_cost <= pre_cost : 70 | pre_cost = current_cost 71 | medoids = best_res 72 | medoids_idx = best_choice 73 | 74 | 75 | return current_cost, best_choice, best_res 76 | 77 | def print_match(best_medoids, blognames) : 78 | for medoid in best_medoids : 79 | print blognames[medoid],'----->', 80 | for m in best_medoids[medoid] : 81 | print '(',m,blognames[m],')', 82 | print 83 | print '---------' * 20 84 | 85 | if __name__ == '__main__' : 86 | ''' 87 | blogwords, blognames = importData() 88 | best_cost,best_choice,best_medoids = kmedoids(blogwords,8) 89 | print_match(best_medoids,blognames) 90 | ''' 91 | #print iris 92 | _, center, res = kmedoids(iris.data, 8) 93 | print center, "\n", res 94 | -------------------------------------------------------------------------------- /dm/preprocess.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import math 3 | 4 | def distinct(rawData): 5 | 6 | def key(row): 7 | newRow = dict(row) 8 | del newRow['id'] 9 | return newRow 10 | 11 | result = [dict(row) for row in rawData] 12 | result.sort(key=key) 13 | 14 | left = 0 15 | for right in xrange(1, len(result)): 16 | if key(result[left]) != key(result[right]) \ 17 | and left + 1 != right: 18 | left += 1 19 | result[left] = result[right] 20 | print left + 1 21 | return result[0:left + 1] 22 | 23 | def removeAbsence(data): 24 | return [row[:] for row in data if None not in row] 25 | 26 | def fillAbsenceWithVal(data, val): 27 | result = [] 28 | for row in data: 29 | result.append([x if x is not None else val for x in row]) 30 | return result 31 | 32 | def fillAbsenceWithAvg(data): 33 | result = [row[:] for row in data] 34 | wid = len(result[0]) 35 | hei = len(result) 36 | avg = [0] * wid 37 | num = [0] * wid 38 | for row in result: 39 | for i in xrange(wid): 40 | elem = row[i]; 41 | if elem is not None: 42 | avg[i] += elem 43 | num[i] += 1 44 | for i in xrange(wid): 45 | if(num[i] != 0): 46 | avg[i] /= num[i] 47 | for row in result: 48 | for i in xrange(wid): 49 | if row[i] is None: 50 | row[i] = avg[i] 51 | return result 52 | 53 | def maxMinRestrict(data): 54 | result = [row[:] for row in data] 55 | wid = len(result[0]) 56 | hei = len(result) 57 | maxList = [-1] * wid 58 | minList = [float('inf')] * wid 59 | for row in result: 60 | for i in xrange(wid): 61 | elem = row[i] 62 | if elem is None: continue 63 | if abs(row[i]) > maxList[i]: 64 | maxList[i] = abs(row[i]) 65 | if abs(row[i]) < minList[i]: 66 | minList[i] = abs(row[i]) 67 | for row in result: 68 | for i in xrange(wid): 69 | elem = row[i] 70 | if elem is None: continue 71 | row[i] = (elem - minList[i]) / (maxList[i] - minList[i]) 72 | return result 73 | 74 | def zScoreRestrict(data): 75 | result = [row[:] for row in data] 76 | wid = len(result[0]) 77 | hei = len(result) 78 | avg = [0] * wid 79 | avgpow2 = [0] * wid 80 | num = [0] * wid 81 | for row in result: 82 | for i in xrange(wid): 83 | elem = row[i]; 84 | if elem is not None: 85 | avg[i] += elem 86 | avgpow2[i] += elem ** 2 87 | num[i] += 1 88 | for i in xrange(wid): 89 | if(num[i] != 0): 90 | avg[i] /= num[i] 91 | avgpow2[i] /= num[i] 92 | sigma = [(avgpow2[i] - avg[i] ** 2) ** 0.5 for i in xrange(wid)] 93 | for row in result: 94 | for i in xrange(wid): 95 | elem = row[i] 96 | if elem is None: continue 97 | row[i] = (elem - avg[i]) / sigma[i] 98 | return result 99 | 100 | def getBit(num): 101 | num = abs(num) 102 | if(num < 1): return 0 103 | else: return math.floor(math.log10(num)) + 1 104 | 105 | def demicalRestrict(data): 106 | result = [row[:] for row in data] 107 | wid = len(result[0]) 108 | hei = len(result) 109 | bits = [0] * wid 110 | for row in result: 111 | for i in xrange(wid): 112 | elem = row[i] 113 | if elem is None: continue 114 | bit = getBit(elem) 115 | if bit > bits[i]: 116 | bits[i] = bit 117 | for row in result: 118 | for i in xrange(wid): 119 | elem = row[i] 120 | if elem is None: continue 121 | row[i] = elem / 10 ** bits[i] 122 | return result -------------------------------------------------------------------------------- /page/result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | 33 | 34 |
    35 |
    36 |

    37 |
    38 | 39 | 40 | 41 |
    42 |
    43 |
    44 | 45 | 46 | 47 |
    48 |
    49 | 50 |
    51 |
    52 | 53 |
    54 |
    55 |
    56 |
    57 |

    X轴属性

    58 |
    59 |
    60 | 61 |
    62 |
    63 |

    Y轴属性

    64 |
    65 |
    66 | 67 |
    68 |
    69 | 70 |
    71 |
    72 |
    73 |
    74 | 75 |
    76 |

    Copyright © 2016 IST LAB

    77 |
    78 |
    79 | 80 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /rmp_simulator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from flask import request, make_response 4 | 5 | import sys 6 | reload(sys) 7 | sys.setdefaultencoding('utf-8') 8 | 9 | import json 10 | json.stringify = json.dumps 11 | json.parse = json.loads 12 | 13 | def iris(token, proj): 14 | from sklearn import datasets 15 | iris = datasets.load_iris() 16 | r = [] 17 | for i in xrange(len(iris.data)): 18 | row = iris.data[i] 19 | elem = { 20 | "id": i, 21 | "col0": int(row[0] * 10) / 10.0, 22 | "col1": int(row[1] * 10) / 10.0, 23 | "col2": int(row[2] * 10) / 10.0, 24 | "col3": int(row[3] * 10) / 10.0, 25 | "label": iris.target[i] 26 | } 27 | r.append(elem) 28 | return json.stringify({'Iris': r}) 29 | 30 | def cart(token, proj): 31 | from dm import loadCart 32 | cart = loadCart() 33 | r = [] 34 | id = 0 35 | for row in cart: 36 | elem = { 37 | "id": id, 38 | "col0": row[0], 39 | "col1": row[1], 40 | "col2": row[2], 41 | "col3": row[3] 42 | } 43 | r.append(elem) 44 | id += 1 45 | return make_response(json.stringify({"Cart": r})) 46 | 47 | def getProj(): 48 | return """ 49 | 50 | 51 | U7f2d2f8faaa9/proj 52 | 53 | 4 54 | 55 | 56 | """ 57 | 58 | def getRsrcList(): 59 | return """ 60 | 61 | 62 | Iris 63 | Tue May 17 2016 10:46:43 64 | loaded 65 | 66 | 67 | Cart 68 | Tue May 17 2016 10:46:43 69 | loaded 70 | 71 | 72 | """ 73 | 74 | def getRsrc(): 75 | rsrc = request.args.get('resource') 76 | if rsrc == 'Iris': 77 | return """ 78 | 79 | 80 | col0 81 | 82 | 83 | 84 | Number 85 | 86 | 87 | col1 88 | 89 | 90 | 91 | Number 92 | 93 | 94 | col2 95 | 96 | 97 | 98 | Number 99 | 100 | 101 | col3 102 | 103 | 104 | 105 | Number 106 | 107 | 108 | label 109 | 110 | 111 | 112 | Number 113 | 114 | 115 | """ 116 | elif rsrc == 'Cart': 117 | return """ 118 | 119 | 120 | col0 121 | 122 | 50 123 | 124 | String 125 | 126 | 127 | col1 128 | 129 | 50 130 | 131 | String 132 | 133 | 134 | col2 135 | 136 | 50 137 | 138 | String 139 | 140 | 141 | col3 142 | 143 | 50 144 | 145 | String 146 | 147 | 148 | """ 149 | else: 150 | return """ 151 | 152 | Column not found! 153 | 154 | """ 155 | 156 | def login(): 157 | return json.stringify({"error": None, "id": 233837063867287}) -------------------------------------------------------------------------------- /dm/apriori.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | def loadDataSet(): 4 | ''' 5 | 创建一个用于测试的简单的数据集 6 | ''' 7 | return [ 8 | [ '豆奶', '莴苣' ], 9 | [ '莴苣', '尿布', '葡萄酒', '甜菜' ], 10 | [ '莴苣', '尿布', '葡萄酒', '橙汁' ], 11 | [ '莴苣', '豆奶', '尿布', '葡萄酒' ], 12 | [ '莴苣', '豆奶', '尿布', '橙汁' ] 13 | ] 14 | 15 | def createC1( dataSet ): 16 | ''' 17 | 构建初始候选项集的列表,即所有候选项集只包含一个元素, 18 | C1是大小为1的所有候选项集的集合 19 | ''' 20 | C1 = [] 21 | for transaction in dataSet: 22 | for item in transaction: 23 | if [ item ] not in C1: 24 | C1.append( [ item ] ) 25 | C1.sort() 26 | return map( frozenset, C1 ) 27 | def scanD( D, Ck, minSupport ): 28 | ''' 29 | 计算Ck中的项集在数据集合D(记录或者transactions)中的支持度, 30 | 返回满足最小支持度的项集的集合,和所有项集支持度信息的字典。 31 | ''' 32 | ssCnt = {} 33 | for tid in D: 34 | # 对于每一条transaction 35 | for can in Ck: 36 | # 对于每一个候选项集can,检查是否是transaction的一部分 37 | # 即该候选can是否得到transaction的支持 38 | if can.issubset( tid ): 39 | ssCnt[ can ] = ssCnt.get( can, 0) + 1 40 | numItems = float( len( D ) ) 41 | retList = [] 42 | supportData = {} 43 | for key in ssCnt: 44 | # 每个项集的支持度 45 | support = ssCnt[ key ] / numItems 46 | # 将满足最小支持度的项集,加入retList 47 | if support >= minSupport: 48 | retList.insert( 0, key ) 49 | # 汇总支持度数据 50 | supportData[ key ] = support 51 | return retList, supportData 52 | 53 | # Aprior算法 54 | def aprioriGen( Lk, k ): 55 | ''' 56 | 由初始候选项集的集合Lk生成新的生成候选项集, 57 | k表示生成的新项集中所含有的元素个数 58 | ''' 59 | retList = [] 60 | lenLk = len( Lk ) 61 | for i in range( lenLk ): 62 | for j in range( i + 1, lenLk ): 63 | L1 = list( Lk[ i ] )[ : k - 2 ]; 64 | L2 = list( Lk[ j ] )[ : k - 2 ]; 65 | L1.sort();L2.sort() 66 | if L1 == L2: 67 | retList.append( Lk[ i ] | Lk[ j ] ) 68 | return retList 69 | def _apriori( dataSet, minSupport = 0.5 ): 70 | # 构建初始候选项集C1 71 | C1 = createC1( dataSet ) 72 | # 将dataSet集合化,以满足scanD的格式要求 73 | D = map( set, dataSet ) 74 | # 构建初始的频繁项集,即所有项集只有一个元素 75 | L1, suppData = scanD( D, C1, minSupport ) 76 | L = [ L1 ] 77 | # 最初的L1中的每个项集含有一个元素,新生成的 78 | # 项集应该含有2个元素,所以 k=2 79 | k = 2 80 | while ( len( L[ k - 2 ] ) > 0 ): 81 | Ck = aprioriGen( L[ k - 2 ], k ) 82 | Lk, supK = scanD( D, Ck, minSupport ) 83 | # 将新的项集的支持度数据加入原来的总支持度字典中 84 | suppData.update( supK ) 85 | # 将符合最小支持度要求的项集加入L 86 | L.append( Lk ) 87 | # 新生成的项集中的元素个数应不断增加 88 | k += 1 89 | # 返回所有满足条件的频繁项集的列表,和所有候选项集的支持度信息 90 | return L, suppData 91 | 92 | # 规则生成与评价 93 | def calcConf( freqSet, H, supportData, brl, minConf=0.7 ): 94 | ''' 95 | 计算规则的可信度,返回满足最小可信度的规则。 96 | freqSet(frozenset):频繁项集 97 | H(frozenset):频繁项集中所有的元素 98 | supportData(dic):频繁项集中所有元素的支持度 99 | brl(tuple):满足可信度条件的关联规则 100 | minConf(float):最小可信度 101 | ''' 102 | prunedH = [] 103 | for conseq in H: 104 | freqSetSupport = supportData[ freqSet ] 105 | srcSupport = supportData[ freqSet - conseq ] 106 | conf = freqSetSupport / srcSupport 107 | if conf >= minConf: 108 | brl.append( ( freqSet - conseq, conseq, conf, freqSetSupport, srcSupport ) ) 109 | prunedH.append( conseq ) 110 | return prunedH 111 | def rulesFromConseq( freqSet, H, supportData, brl, minConf=0.7 ): 112 | ''' 113 | 对频繁项集中元素超过2的项集进行合并。 114 | freqSet(frozenset):频繁项集 115 | H(frozenset):频繁项集中的所有元素,即可以出现在规则右部的元素 116 | supportData(dict):所有项集的支持度信息 117 | brl(tuple):生成的规则 118 | ''' 119 | m = len( H[ 0 ] ) 120 | # 查看频繁项集是否大到移除大小为 m 的子集 121 | if len( freqSet ) > m + 1: 122 | Hmp1 = aprioriGen( H, m + 1 ) 123 | Hmp1 = calcConf( freqSet, Hmp1, supportData, brl, minConf ) 124 | # 如果不止一条规则满足要求,进一步递归合并 125 | if len( Hmp1 ) > 1: 126 | rulesFromConseq( freqSet, Hmp1, supportData, brl, minConf ) 127 | def generateRules( L, supportData, minConf=0.7 ): 128 | ''' 129 | 根据频繁项集和最小可信度生成规则。 130 | L(list):存储频繁项集 131 | supportData(dict):存储着所有项集(不仅仅是频繁项集)的支持度 132 | minConf(float):最小可信度 133 | 返回值:( freqSet - conseq, conseq, conf )的数组 134 | ''' 135 | bigRuleList = [] 136 | for i in range( 1, len( L ) ): 137 | for freqSet in L[ i ]: 138 | # 对于每一个频繁项集的集合freqSet 139 | H1 = [ frozenset( [ item ] ) for item in freqSet ] 140 | # 如果频繁项集中的元素个数大于2,需要进一步合并 141 | if i > 1: 142 | rulesFromConseq( freqSet, H1, supportData, bigRuleList, minConf ) 143 | else: 144 | calcConf( freqSet, H1, supportData, bigRuleList, minConf ) 145 | return bigRuleList 146 | 147 | 148 | def apriori(dataSet, **kwargs): 149 | minSupport = kwargs.get('minSupport') 150 | if minSupport is None: minSupport = 0.5 151 | minConf = kwargs.get('minConf') 152 | if minConf is None: minConf = 0.7 153 | L, suppData = _apriori(dataSet, minSupport) 154 | return generateRules(L, suppData, minConf) 155 | 156 | def printRules(rules): 157 | for row in rules: 158 | print '{0} ----> {1} conf: {2} support: {3}, {4}'.format( 159 | ', '.join(row[0]), 160 | ', '.join(row[1]), 161 | row[2], 162 | row[3], 163 | row[4] 164 | ) 165 | 166 | if __name__ == '__main__': 167 | myDat = loadDataSet() 168 | rules = apriori(myDat) 169 | printRules(rules) -------------------------------------------------------------------------------- /page/js/util.js: -------------------------------------------------------------------------------- 1 | function getUrl() { 2 | return 'http://202.120.40.73:28080'; 3 | //return 'http://localhost:5000'; 4 | } 5 | 6 | function getUser() { 7 | var id = localStorage.getItem('id'); 8 | var un = localStorage.getItem('un'); 9 | var pw = localStorage.getItem('pw'); 10 | 11 | if(id && un && pw) 12 | return { 13 | id: id, 14 | un: un, 15 | pw: pw 16 | } 17 | else return null; 18 | } 19 | 20 | function setUser(id, un, pw) { 21 | localStorage.setItem('id', id); 22 | localStorage.setItem('un', un); 23 | localStorage.setItem('pw', pw); 24 | } 25 | 26 | function htmlSpecialChars(s) { 27 | return s.replace(//g, '>') 29 | .replace(/&/g, '&') 30 | .replace(/"/g, '"') 31 | .replace(/'/g, '''); 32 | } 33 | 34 | var statusMap = { 35 | 1: 'View Resouce', 36 | 2: 'Manage Resource', 37 | 3: 'Delete Object', 38 | 4: 'Previlege Assignment' 39 | }; 40 | 41 | var algos = { 42 | assoc: ['apriori'], 43 | classify: ['knn', 'svm', 'naive_bayes'], 44 | cluster: ['kmeans', 'kmedoids'] 45 | }; 46 | 47 | var algoDict = { 48 | assoc: "关联", 49 | classify: "分类", 50 | cluster: "聚类", 51 | apriori: "Apriori", 52 | knn: "KNN", 53 | svm: "SVM", 54 | naive_bayes: "Naive Bayes", 55 | kmeans: "Kmeans", 56 | kmedoids: "Kmedoids" 57 | }; 58 | 59 | var $getPagBtn = function(data, text) { 60 | return $(''); 63 | }; 64 | 65 | var pageCap = 10; 66 | 67 | var loadPagBar = function(cur, total, data) { 68 | if(cur > total) throw new Error(); 69 | 70 | $('#pag-bar').empty(); 71 | var pages; 72 | if(cur == 1 || cur == 2) 73 | pages = [1, 2, 3, 4, 5]; 74 | else if(cur == total || cur == total - 1) 75 | pages = [total - 4, total - 3, total - 2, total - 1, total]; 76 | else 77 | pages = [cur - 2, cur - 1, cur, cur + 1, cur + 2]; 78 | pages = pages.filter(function(x){return x > 0 && x <= total;}); 79 | 80 | var result = []; 81 | if(cur != 1) { 82 | var $prev = $getPagBtn(cur - 1, '上一页'); 83 | $prev.addClass('pag-prev'); 84 | result.push($prev); 85 | } 86 | 87 | 88 | var $nums = $('
    '); 89 | result.push($nums); 90 | if(pages.indexOf(1) == -1) { 91 | $getPagBtn(1, 1).appendTo($nums); 92 | $getPagBtn('', '...').appendTo($nums); 93 | } 94 | 95 | for(var i in pages) { 96 | $getPagBtn(pages[i], pages[i]).appendTo($nums); 97 | } 98 | 99 | if(pages.indexOf(total) == -1) { 100 | $getPagBtn('', '...').appendTo($nums); 101 | $getPagBtn(total, total).appendTo($nums); 102 | } 103 | 104 | if(cur != total && total != 1) { 105 | var $next = $getPagBtn(cur + 1, '下一页'); 106 | $next.addClass('pag-next'); 107 | result.push($next); 108 | } 109 | 110 | for(var i = 0; i < result.length; i++) 111 | $('#pag-bar').append(result[i]); 112 | $('.pag-btn').click(function(){refreshPage.call(this, total, data)}); 113 | }; 114 | 115 | var refreshPage = function(total, data) { 116 | var pg = $(this).data('pg'); 117 | if(pg == '') return; 118 | loadPagBar(pg, total, data); 119 | loadResult(data.slice((pg - 1) * pageCap, pg * pageCap)); 120 | }; 121 | 122 | var keys = function(o) { 123 | var keys = []; 124 | for(var k in o) 125 | keys.push(k); 126 | return keys; 127 | }; 128 | 129 | var values = function(o) { 130 | var values = []; 131 | for(var k in o) 132 | values.push(o[k]); 133 | return values; 134 | }; 135 | 136 | var labelToColor = function(i) { 137 | var m = [ 138 | "#993", "#C9C", "#C96", "#666", "#C99", "#CC9", "#333", "#96C" 139 | ]; 140 | 141 | return m[i % m.length]; 142 | }; 143 | 144 | // 阻塞延迟 145 | function sleep(milliSeconds) { 146 | var startTime = new Date().getTime(); 147 | while (new Date().getTime() < startTime + milliSeconds); 148 | } 149 | 150 | // 两点连线与x轴的夹角,如果两点相同返回0 151 | function slopeAngle(p1, p2) { 152 | var angle = Math.atan2(p2.y - p1.y, p2.x - p1.x); 153 | if (angle < 0) angle += Math.PI * 2; 154 | return angle; 155 | } 156 | 157 | 158 | function distance(p1, p2) { 159 | return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); 160 | } 161 | 162 | // 返回最下面的点,如果y值相同则返回左边的点 163 | function findMostLeftBottom(arr) { 164 | if(arr.length == 0) throw new Error(); 165 | var res = arr[0]; 166 | for(var i = 1; i < arr.length; i++) { 167 | var p = arr[i]; 168 | if(p.y < res.y || (p.y == res.y && p.x < res.x)) 169 | res = p; 170 | } 171 | return res; 172 | } 173 | 174 | // Graham扫描算法 175 | function graham(arr) { 176 | 177 | arr = arr.slice(); 178 | var lbMost = findMostLeftBottom(arr); 179 | var pos = arr.indexOf(lbMost); 180 | arr.splice(pos, 1); 181 | 182 | arr.sort(function(p1, p2) { 183 | var theta1 = slopeAngle(lbMost, p1); 184 | var theta2 = slopeAngle(lbMost, p2); 185 | if(theta1 != theta2) 186 | return theta1 - theta2; 187 | else 188 | return distance(p1, lbMost) - distance(p2, lbMost); 189 | }) 190 | 191 | var res = [lbMost]; 192 | for(var i = 0; i < arr.length; i++) { 193 | var p = arr[i]; 194 | if(res.length < 3) 195 | res.push(p); 196 | else { 197 | var p1 = res[res.length - 2], 198 | p2 = res[res.length - 1]; 199 | var theta1 = slopeAngle(p1, p2), 200 | theta2 = slopeAngle(p2, p); 201 | if(theta1 < theta2) // 左转保留 202 | res.push(p); 203 | else // 右转舍弃 204 | { 205 | res.pop(); 206 | i--; 207 | } 208 | } 209 | } 210 | return res; 211 | } 212 | 213 | var getTimeStr = function(tm) { 214 | 215 | var tm = tm || new Date(); 216 | var o = { 217 | yr: tm.getFullYear(), 218 | mon: tm.getMonth() + 1, 219 | dt: tm.getDate(), 220 | hr: tm.getHours(), 221 | min: tm.getMinutes(), 222 | sec: tm.getSeconds() 223 | }; 224 | for(var i in o) 225 | { 226 | o[i] = o[i].toString(); 227 | if(o[i].length < 2) 228 | o[i] = '0' + o[i]; 229 | } 230 | return o.yr + '-' + o.mon + '-' + o.dt + 231 | ' ' + o.hr + ':' + o.min + ':' + o.sec; 232 | }; -------------------------------------------------------------------------------- /page/js/mining.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | 3 | var selected = {}; 4 | 5 | 6 | var getCols = function() { 7 | 8 | $('#modal-loading').modal('show'); 9 | var user = getUser(); 10 | var proj = localStorage.getItem('proj'); 11 | var token = localStorage.getItem('token'); 12 | var rsrc = localStorage.getItem('rsrc'); 13 | $('#rsrc-name').text(rsrc); 14 | 15 | var url = getUrl() + '/System/Resource?userid=' + user.id + '&project=' + 16 | token + '/' + proj + '&resource=' + rsrc 17 | $.ajax({ 18 | type: "GET", 19 | url: url, 20 | dataType: "xml", 21 | beforeSend: function (request) { 22 | request.setRequestHeader("passwd", user.pw); 23 | } 24 | }).done(function(data){ 25 | var $data = $(data); 26 | var errmsg = $data.find("error").text(); 27 | if (errmsg.length !== 0) 28 | alert(errmsg); 29 | else 30 | loadCols($(data).find("Column")); 31 | $('#modal-loading').modal('hide'); 32 | }).fail(function(data, status, e){ 33 | alert("network error"); 34 | $('#modal-loading').modal('hide'); 35 | }); 36 | }; 37 | 38 | var loadCols = function($list) { 39 | $('.cols-row').remove(); 40 | for(var i = 0; i < $list.length; i++) 41 | { 42 | var $item = $list.eq(i); 43 | var name = $item.children('ColumnName').text(); 44 | var alias = $item.children('AttributeName').text() || "(未设置)"; 45 | var size = $item.children('Size').text(); 46 | //var isNotNull = $item.children('NotNull').text(); 47 | var type = $item.children('Type').text(); 48 | if(size) type += ' * ' + size; 49 | 50 | var $tr = $(''); 51 | var $nameTd = $('' + name + ''); 52 | var $aliasTd = $('' + alias + ''); 53 | var $typeTd = $('' + type + ''); 54 | var $isNotNullTd = $('是'); 55 | var $opTd = $(''); 56 | var $selectCheck = $(''); 57 | $opTd.append($selectCheck); 58 | $tr.append($nameTd); 59 | $tr.append($aliasTd); 60 | $tr.append($typeTd); 61 | $tr.append($isNotNullTd); 62 | $tr.append($opTd); 63 | $('#cols-table').append($tr); 64 | } 65 | $('.cols-select').click(selectCol); 66 | }; 67 | 68 | var selectCol = function() { 69 | 70 | var $this = $(this); 71 | var name = $this.parent().parent().children('.cols-name').text(); 72 | 73 | if($this.is(':checked')) 74 | selected[name] = name; 75 | else 76 | delete selected[name]; 77 | 78 | console.log(selected); 79 | }; 80 | 81 | var mining = function() { 82 | 83 | var uid = localStorage['id']; 84 | var proj = localStorage.getItem('proj'); 85 | var token = localStorage.getItem('token'); 86 | var rsrc = localStorage.getItem('rsrc'); 87 | 88 | var type = $('#type-combo').val(); 89 | var algo = $('#algo-combo').val(); 90 | var start = $('#start-num').val(); 91 | var count = $('#count-num').val(); 92 | if(count == "-1") count = ""; 93 | 94 | var title = $('#title-txt').val(); 95 | if(title == "") 96 | { 97 | alert('名称不能为空!'); 98 | return; 99 | } 100 | 101 | var cols = keys(selected); 102 | if(cols.length == 0) 103 | { 104 | alert('请选择要挖掘的列!'); 105 | return; 106 | } 107 | cols = JSON.stringify(cols); 108 | 109 | var args = {} 110 | if(algo == "apriori") { 111 | var minSupport = $('#apriori-min-support').val(); 112 | var minConf = $('#apriori-min-conf').val(); 113 | minSupport = parseFloat(minSupport); 114 | minConf = parseFloat(minConf); 115 | if(isNaN(minSupport) || isNaN(minConf)) { 116 | alert('参数格式有误!'); 117 | return; 118 | } 119 | args = { 120 | minSupport: minSupport, 121 | minConf: minConf 122 | } 123 | } 124 | else if(algo == "kmeans") { 125 | var n_clusters = parseInt($('#kmeans-label-num').val()); 126 | var max_iter = parseInt($('#kmeans-max-iter').val()); 127 | var init = $('#kmeans-init').val(); 128 | var precompute_distances = $('#kmeans-pre-dist').val(); 129 | if(precompute_distances != 'auto') precompute_distances = precompute_distances == 'true' 130 | tol = parseFloat($('#kmeans-tol').val()); 131 | if(isNaN(n_clusters) || isNaN(max_iter) || 132 | ['k-means++', 'random'].indexOf(init) == -1 || 133 | ['auto', true, false].indexOf(precompute_distances) == -1 || 134 | isNaN(tol)) { 135 | alert('参数格式有误!'); 136 | return; 137 | } 138 | args = { 139 | n_clusters: n_clusters, 140 | max_iter: max_iter, 141 | init: init, 142 | precompute_distances: precompute_distances, 143 | tol: tol 144 | }; 145 | } 146 | else if(algo == "kmedoids") { 147 | var k = $('#kmedoids-label-num').val(); 148 | k = parseInt(k); 149 | if(isNaN(k)) { 150 | alert('参数格式有误!'); 151 | return; 152 | } 153 | args = { 154 | k: k 155 | }; 156 | } 157 | else if (algo == "svm") { 158 | var C = parseFloat($('#svm-c').val()); 159 | var kernel = $('#svm-kernel').val(); 160 | var degree = parseInt($('#svm-degree').val()); 161 | var gamma = $('#svm-gamma').val(); 162 | if(gamma != 'auto') gamma = parseFloat(gamma); 163 | var coef0 = parseFloat($('#svm-coef0').val()); 164 | var probability = $('#svm-probability').val() == 'true'; 165 | var shrinking = $('#svm-shrinking').val() == 'true'; 166 | var tol = parseFloat($('#svm-tol').val()); 167 | if(isNaN(C) || isNaN(degree) || (gamma != 'auto' && isNaN(gamma)) || 168 | isNaN(coef0) || isNaN(tol)) { 169 | alert('参数格式有误!'); 170 | return; 171 | } 172 | args = { 173 | C: C, 174 | kernel: kernel, 175 | degree: degree, 176 | gamma: gamma, 177 | coef0: coef0, 178 | probability: probability, 179 | shrinking: shrinking, 180 | tol: tol 181 | } 182 | console.log(args); 183 | } 184 | args = JSON.stringify(args); 185 | 186 | var url = './mining/' + uid + '/' + token + '/' + proj + '/' + rsrc + '/'; 187 | var data = 'algo=' + algo + '&start=' + start + "&count=" + 188 | count + '&cols=' + encodeURIComponent(cols) + '&title=' + 189 | encodeURIComponent(title) + '&args=' + encodeURIComponent(args); 190 | 191 | if(type == "classify") 192 | { 193 | var predictStart = $('#predict-start-num').val(); 194 | var predictCount = $('#predict-count-num').val(); 195 | if(predictCount == "-1") predictCount = ""; 196 | var label = $('#predict-label-text').val(); 197 | if(label == "") 198 | { 199 | alert('请填写标签。'); 200 | return; 201 | } 202 | 203 | data += '&predictStart=' + predictStart + '&predictCount=' + 204 | predictCount + '&label=' + label; 205 | } 206 | 207 | if(type != 'assoc') { 208 | var absent = $('#absent-combo').val(); 209 | var fillval = $('#fillval-text').val(); 210 | var formal = $('#formal-combo').val(); 211 | var distinct = $('#distinct-cb').is(':checked').toString(); 212 | data += '&absent=' + absent + '&fillval=' + 213 | fillval + '&formal=' + formal + '&distinct=' + distinct; 214 | } 215 | 216 | $.ajax({ 217 | type: "POST", 218 | url: url, 219 | data: data, 220 | dataType: "json", 221 | contentType: "application/x-www-form-urlencoded" 222 | }).done(function(data){ 223 | if(!data.succ) 224 | alert(data.msg); 225 | else { 226 | alert('已提交。'); 227 | location.href = './history.html'; 228 | } 229 | }).fail(function(data, status, e){ 230 | alert("network error"); 231 | }); 232 | }; 233 | 234 | var initAlgoType = function() { 235 | 236 | var $typeCombo = $('#type-combo'); 237 | for(type in algos) 238 | $('').appendTo($typeCombo); 239 | $typeCombo.on('change', changeAlgoType); 240 | changeAlgoType.call($typeCombo); 241 | var $algoCombo = $('#algo-combo'); 242 | $algoCombo.on('change', changeAlgo); 243 | changeAlgo.call($algoCombo); 244 | }; 245 | 246 | var changeAlgoType = function() { 247 | 248 | var type = $(this).val(); 249 | var $algoCombo = $('#algo-combo'); 250 | $algoCombo.empty(); 251 | for(var i in algos[type]) 252 | { 253 | var algo = algos[type][i]; 254 | $('').appendTo($algoCombo); 255 | } 256 | 257 | if(type == "classify") 258 | $('.classify-req').removeClass('hidden'); 259 | else 260 | $('.classify-req').addClass('hidden'); 261 | 262 | if(type == 'assoc') 263 | $('#prepro-panel').addClass('hidden'); 264 | else 265 | $('#prepro-panel').removeClass('hidden') 266 | 267 | $algoCombo.on('change', changeAlgo); 268 | changeAlgo.call($algoCombo); 269 | }; 270 | 271 | var absentComboOnClick = function() { 272 | if($('#absent-combo').val() == "val") 273 | $('.fillval').removeClass('hidden'); 274 | else 275 | $('.fillval').addClass('hidden'); 276 | }; 277 | 278 | var changeAlgo = function() { 279 | $('.args').addClass('hidden'); 280 | var algo = $('#algo-combo').val(); 281 | if(algo == "apriori") 282 | $('#apriori-arg').removeClass('hidden'); 283 | else if (algo == "kmeans") 284 | $('#kmeans-arg').removeClass('hidden'); 285 | else if (algo == "kmedoids") 286 | $('#kmedoids-arg').removeClass('hidden'); 287 | else if (algo == "svm") 288 | $('#svm-arg').removeClass('hidden'); 289 | }; 290 | 291 | getCols(); 292 | initAlgoType(); 293 | $('#mining-btn').click(mining); 294 | $('#absent-combo').click(absentComboOnClick); 295 | }); -------------------------------------------------------------------------------- /page/mining.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 | 32 | 33 |
    34 |
    35 |

    属性

    36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
    名称别名类型是否非空选定
    46 |
    47 | 48 |
    49 |
    50 |

    基本设置

    51 |
    52 |
    53 |
    54 |
    55 |

    名称

    56 |
    57 |
    58 | 59 |
    60 |
    61 |
    62 |
    63 |

    算法类别

    64 |
    65 |
    66 | 67 |
    68 |
    69 |

    算法

    70 |
    71 |
    72 | 73 |
    74 |
    75 |
    76 |
    77 |

    起始位置

    78 |
    79 |
    80 | 81 |
    82 |
    83 |

    数量

    84 |
    85 |
    86 | 87 |
    88 |
    89 |
    90 |
    91 |

    预测集起始位置

    92 |
    93 |
    94 | 95 |
    96 |
    97 |

    预测集数量

    98 |
    99 |
    100 | 101 |
    102 |
    103 |
    104 |
    105 |

    标签

    106 |
    107 |
    108 | 109 |
    110 |
    111 |
    112 |
    113 | 114 |
    115 |
    116 |

    预处理

    117 |
    118 |
    119 |
    120 |
    121 |

    缺失值

    122 |
    123 |
    124 | 130 |
    131 | 134 | 137 |
    138 |
    139 |
    140 |

    规范化

    141 |
    142 |
    143 | 149 |
    150 |
    151 |
    152 |
    153 |

    去重复

    154 |
    155 |
    156 | 158 |
    159 |
    160 |
    161 |
    162 | 163 |
    164 |
    165 |

    参数

    166 |
    167 |
    168 |
    169 |
    170 |

    最小支持度

    171 |
    172 |
    173 | 174 |
    175 |
    176 |

    最小置信度

    177 |
    178 |
    179 | 180 |
    181 |
    182 |
    183 | 184 |
    185 |
    186 |
    187 |

    标签数

    188 |
    189 |
    190 | 191 |
    192 |
    193 |

    最大迭代数

    194 |
    195 |
    196 | 197 |
    198 |
    199 |

    最大迭代数

    200 |
    201 |
    202 | 206 |
    207 |
    208 |

    预计算距离

    209 |
    210 |
    211 | 216 |
    217 |
    218 |

    容忍度

    219 |
    220 |
    221 | 222 |
    223 |
    224 |
    225 | 226 |
    227 |
    228 |
    229 |

    标签数

    230 |
    231 |
    232 | 233 |
    234 |
    235 |
    236 | 237 |
    238 |
    239 |
    240 |

    C

    241 |
    242 |
    243 | 244 |
    245 |
    246 |

    Kernel

    247 |
    248 |
    249 | 256 |
    257 |
    258 |

    Degree

    259 |
    260 |
    261 | 262 |
    263 |
    264 |

    Gamma

    265 |
    266 |
    267 | 268 |
    269 |
    270 |

    Coef0

    271 |
    272 |
    273 | 274 |
    275 |
    276 |

    Probability

    277 |
    278 |
    279 | 283 |
    284 |
    285 |

    Shrinking

    286 |
    287 |
    288 | 292 |
    293 |
    294 |

    Tol

    295 |
    296 |
    297 | 298 |
    299 |
    300 |
    301 |
    302 |

    参数的详细解释请见sklearn.svm.SVC文档。

    303 |
    304 |
    305 |
    306 |
    307 | 308 |
    309 |
    310 | 312 |
    313 |
    314 | 315 |
    316 |

    Copyright © 2016 IST LAB

    317 |
    318 |
    319 | 320 | 339 | 340 | 341 | -------------------------------------------------------------------------------- /page/js/result.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var id = localStorage.getItem('resultId'); 4 | var type = localStorage.getItem('resultType'); 5 | var rsrc = localStorage.getItem('resultRsrc'); 6 | $('#rsrc-name').text(rsrc); 7 | 8 | $resultHeadTr = $('#result-head'); 9 | if(type == 'assoc') 10 | { 11 | $('关联规则').appendTo($resultHeadTr); 12 | $('置信度').appendTo($resultHeadTr); 13 | } 14 | else if(type == 'classify' || type == 'cluster') 15 | { 16 | $('id').appendTo($resultHeadTr); 17 | $('原始数据').appendTo($resultHeadTr); 18 | $('标签').appendTo($resultHeadTr); 19 | } 20 | else 21 | throw new Error(); 22 | 23 | var getResult = function() { 24 | 25 | $('#modal-loading').modal('show'); 26 | $.ajax({ 27 | type: "GET", 28 | url: "result/" + id + '/', 29 | dataType: "json" 30 | }).done(function(json) { 31 | if (!json.succ) 32 | alert(json.errmsg); 33 | else { 34 | var data = json.data; 35 | if(type != 'assoc') 36 | data = data.map(function(e){return [e[0], e[1], JSON.parse(e[2])]}); 37 | //window.data = data; 38 | var totalPage = Math.floor((data.length - 1) / pageCap) + 1; 39 | loadPagBar(1, totalPage, data); 40 | loadResult(data.slice(0, pageCap)); 41 | loadCharts(data); 42 | $('#modal-loading').modal('hide'); 43 | } 44 | }).fail(function(data) { 45 | alert('Network error!'); 46 | $('#modal-loading').modal('hide'); 47 | }); 48 | }; 49 | 50 | 51 | var loadResult = function(list) { 52 | 53 | 54 | $('.result-row').remove(); 55 | for (var i = 0; i < list.length; i++) { 56 | var elem = list[i]; 57 | 58 | var $tr = $('') 59 | 60 | if(type == 'assoc') 61 | { 62 | var $ruleTd = $('' + elem[2] + ''); 63 | var $confTd = $('' + elem[1] + ''); 64 | $tr.append($ruleTd); 65 | $tr.append($confTd); 66 | } 67 | else if(type == 'cluster' || type == 'classify') 68 | { 69 | var dataStr = htmlSpecialChars(formatData(elem[2])); 70 | //var $idTd = $('' + elem[0] + ''); 72 | var $idTd = $('' + elem[0] + ''); 73 | var $dataTd = $('' + dataStr + ''); 74 | var $labelTd = $('' + elem[1] + ''); 75 | $tr.append($idTd); 76 | $tr.append($dataTd); 77 | $tr.append($labelTd); 78 | } 79 | else 80 | throw new Error(); 81 | 82 | $('#result-table').append($tr); 83 | } 84 | //$('[data-toggle="tooltip"]').tooltip() 85 | }; 86 | window.loadResult = loadResult; 87 | 88 | var formatData = function(data) { 89 | var arr = []; 90 | for(var k in data) 91 | arr.push(k + ': ' + data[k]); 92 | return arr.join(', '); 93 | }; 94 | 95 | var loadCharts = function(list) { 96 | 97 | if(type == 'cluster' || type == 'classify') { 98 | 99 | var keyList = keys(list[0][2]); 100 | 101 | loadTotalChart(list); 102 | loadDistChart(list, keyList.slice(0, 2)); 103 | 104 | var $keyOptions = keyList.map(function(k){return $('');}); 105 | $('#col1-combo').append($keyOptions); 106 | $keyOptions = keyList.map(function(k){return $('');}); 107 | $('#col2-combo').append($keyOptions); 108 | $('#gen-btn').click(function(){genDistChart(list);}); 109 | } 110 | else if(type == 'assoc') { 111 | $('.visual-control').addClass('hidden'); 112 | loadTotalChartAssoc(list); 113 | loadDistChartAssoc(list); 114 | } 115 | else 116 | throw new Error(); 117 | 118 | }; 119 | 120 | var loadTotalChart = function(list) { 121 | $('#total-svg').empty(); 122 | 123 | var labelCountMap = {}; 124 | for (var i = 0; i < list.length; i++) { 125 | var elem = list[i]; 126 | var label = elem[1]; 127 | var num = labelCountMap[label] || 0; 128 | labelCountMap[label] = num + 1; 129 | } 130 | var labels = keys(labelCountMap); 131 | var counts = values(labelCountMap); 132 | 133 | var svg = d3.select("#total-svg"); 134 | var width = svg.attr("width"); 135 | var height = svg.attr("height") - 20; 136 | var xScale = d3.scale.ordinal() 137 | .domain(d3.range(counts.length)) 138 | .rangeRoundBands([0, width]); 139 | var yScale = d3.scale.linear() 140 | .domain([0,d3.max(counts)]) 141 | .range([height, 0]); 142 | var rectPadding = 4; 143 | var rects = svg.selectAll(".rect") 144 | .data(counts) 145 | .enter() 146 | .append("rect") 147 | //.attr("class", "MyRect") 148 | //.attr("transform", "translate(" + padding.left + "," + padding.top + ")") 149 | .attr("x", function(d,i){ 150 | return xScale(i) + rectPadding/2; 151 | } ) 152 | .attr("y",function(d){ 153 | return yScale(d); 154 | }) 155 | .attr("width", xScale.rangeBand() - rectPadding ) 156 | .attr("height", function(d){ 157 | return height - yScale(d); 158 | }) 159 | .attr("fill", function(d, i) { 160 | return labelToColor(labels[i]); 161 | }); 162 | 163 | var texts = svg.selectAll(".text") 164 | .data(counts) 165 | .enter() 166 | .append("text") 167 | //.attr("class","MyText") 168 | //.attr("transform","translate(" + padding.left + "," + padding.top + ")") 169 | .attr("x", function(d,i){ 170 | return xScale(i) + rectPadding/2; 171 | } ) 172 | .attr("y",function(d){ 173 | return yScale(d); 174 | }) 175 | .attr("dx",function(){ 176 | return (xScale.rangeBand() - rectPadding)/2 - 10; 177 | }) 178 | .attr("dy", 20) 179 | .text(function(d){ 180 | return d; 181 | }) 182 | .attr('fill', 'white'); 183 | 184 | var texts = svg.selectAll(".label") 185 | .data(labels) 186 | .enter() 187 | .append("text") 188 | //.attr("class","MyText") 189 | //.attr("transform","translate(" + padding.left + "," + padding.top + ")") 190 | .attr("x", function(d,i){ 191 | return xScale(i) + rectPadding/2; 192 | } ) 193 | .attr("y", height) 194 | .attr("dx",function(){ 195 | return (xScale.rangeBand() - rectPadding)/2 - 5; 196 | }) 197 | .attr("dy", 20) 198 | .text(function(d){ 199 | return d; 200 | }) 201 | .attr('fill', 'black'); 202 | }; 203 | 204 | var genDistChart = function(data) { 205 | var col1 = $('#col1-combo').val(); 206 | var col2 = $('#col2-combo').val(); 207 | if(!col1 || !col2) return; 208 | loadDistChart(data, [col1, col2]); 209 | }; 210 | 211 | var loadDistChart = function(data, cols) { 212 | 213 | $('#dist-svg').empty(); 214 | 215 | var xCol = cols[0]; 216 | if(!xCol) throw new Error(); 217 | var yCol = cols[1] || cols[0]; 218 | var xArr = data.map(function(e){return e[2][xCol];}) 219 | var yArr = data.map(function(e){return e[2][yCol];}) 220 | 221 | var padding = {left: 30, right: 10, top: 10, bottom: 20}; 222 | var svg = d3.select("#dist-svg"); 223 | var width = svg.attr("width") - padding.left - padding.right; 224 | var height = svg.attr("height") - padding.top - padding.bottom; 225 | var xScale = d3.scale.linear() 226 | .domain([0, d3.max(xArr)]) 227 | .range([0, width]); 228 | var yScale = d3.scale.linear() 229 | .domain([0, d3.max(yArr)]) 230 | .range([height, 0]); 231 | 232 | var circles = svg.selectAll('.circle') 233 | .data(data) 234 | .enter() 235 | .append("circle") 236 | .attr('cx', function(d) { 237 | return xScale(d[2][xCol]); 238 | console.log(d); 239 | }) 240 | .attr('cy', function(d) { 241 | return yScale(d[2][yCol]); 242 | }) 243 | .attr('r', 3) 244 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 245 | .attr('fill', function(d) { 246 | return labelToColor(d[1]); 247 | }); 248 | 249 | var yAxis = d3.svg.axis() 250 | .scale(yScale) 251 | .orient("left"); 252 | svg.append("g") 253 | .attr("class","axis") 254 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 255 | .call(yAxis); 256 | 257 | var xAxis = d3.svg.axis() 258 | .scale(xScale) 259 | .orient("bottom"); 260 | svg.append("g") 261 | .attr("class","axis") 262 | .attr("transform","translate(" + padding.left + "," + (height + padding.top) + ")") 263 | .call(xAxis); 264 | 265 | // 绘制凸包 266 | var pointsByLabel = {}; 267 | for (var i = 0; i < data.length; i++) { 268 | var elem = data[i]; 269 | var label = elem[1]; 270 | var arr = pointsByLabel[label] || []; 271 | var p = {x: elem[2][xCol], y: elem[2][yCol]}; 272 | arr.push(p); 273 | pointsByLabel[label] = arr; 274 | } 275 | 276 | for (var label in pointsByLabel) { 277 | console.log('label: ' + label); 278 | console.log('points: ' + JSON.stringify(pointsByLabel[label])); 279 | var convex = graham(pointsByLabel[label]); 280 | var linesData = []; 281 | for(var i = 0; i < convex.length - 1; i++) 282 | linesData.push([convex[i], convex[i + 1]]); 283 | linesData.push([convex[convex.length - 1], convex[0]]); 284 | console.log('lines: ' + JSON.stringify(linesData)); 285 | 286 | var lines = svg.selectAll('.line') 287 | .data(linesData) 288 | .enter() 289 | .append('line') 290 | .attr('x1', function(d) {return xScale(d[0].x);}) 291 | .attr('y1', function(d) {return yScale(d[0].y);}) 292 | .attr('x2', function(d) {return xScale(d[1].x);}) 293 | .attr('y2', function(d) {return yScale(d[1].y);}) 294 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 295 | .attr('stroke', labelToColor(label)); 296 | } 297 | }; 298 | 299 | var loadTotalChartAssoc = function(data) { 300 | 301 | $('#total-svg').empty(); 302 | 303 | supportData = {} 304 | for(var i = 0; i < data.length; i++) { 305 | elem = data[i]; 306 | tmp = elem[2].split(' -> '); 307 | src = tmp[0]; 308 | freq = tmp[1].split(', ').concat(src.split(', ')).sort().join(', '); 309 | supportData[freq] = elem[3]; 310 | supportData[src] = elem[4]; 311 | } 312 | var labels = keys(supportData); 313 | var counts = values(supportData); 314 | 315 | var svg = d3.select("#total-svg"); 316 | var width = svg.attr("width"); 317 | var height = svg.attr("height") - 30; 318 | var xScale = d3.scale.ordinal() 319 | .domain(d3.range(counts.length)) 320 | .rangeRoundBands([0, width]); 321 | var yScale = d3.scale.linear() 322 | .domain([0,d3.max(counts)]) 323 | .range([height, 0]); 324 | var rectPadding = 4; 325 | var rects = svg.selectAll(".rect") 326 | .data(counts) 327 | .enter() 328 | .append("rect") 329 | //.attr("class", "MyRect") 330 | //.attr("transform", "translate(" + padding.left + "," + padding.top + ")") 331 | .attr("x", function(d,i){ 332 | return xScale(i) + rectPadding/2; 333 | } ) 334 | .attr("y",function(d){ 335 | return yScale(d); 336 | }) 337 | .attr("width", xScale.rangeBand() - rectPadding ) 338 | .attr("height", function(d){ 339 | return height - yScale(d); 340 | }) 341 | .attr("fill", function(d, i) { 342 | return labelToColor(i); 343 | }); 344 | 345 | var texts = svg.selectAll(".text") 346 | .data(counts) 347 | .enter() 348 | .append("text") 349 | //.attr("class","MyText") 350 | //.attr("transform","translate(" + padding.left + "," + padding.top + ")") 351 | .attr("x", function(d,i){ 352 | return xScale(i) + rectPadding/2; 353 | } ) 354 | .attr("y",function(d){ 355 | return yScale(d); 356 | }) 357 | .attr("dx",function(){ 358 | return (xScale.rangeBand() - rectPadding)/2 - 10; 359 | }) 360 | .attr("dy", 20) 361 | .text(function(d){ 362 | return d; 363 | }) 364 | .attr('fill', 'white'); 365 | 366 | var texts = svg.selectAll(".label") 367 | .data(labels) 368 | .enter() 369 | .append("text") 370 | //.attr("class","MyText") 371 | //.attr("transform","translate(" + padding.left + "," + padding.top + ")") 372 | .attr("x", function(d,i){ 373 | return xScale(i) + rectPadding/2; 374 | } ) 375 | .attr("y", height) 376 | .attr("dx",function(d){ 377 | var len = d.length * 10; 378 | return (xScale.rangeBand() - rectPadding - len) / 2 ; 379 | }) 380 | .attr("dy", 20) 381 | .text(function(d){ 382 | return d; 383 | }) 384 | .attr('fill', 'black'); 385 | } 386 | 387 | var loadDistChartAssoc = function (data) { 388 | 389 | $('#dist-svg').empty(); 390 | 391 | var dataDict = {}; 392 | var srcSet = {}; 393 | var dstSet = {}; 394 | for(var i = 0; i < data.length; i++) { 395 | var elem = data[i]; 396 | dataDict[elem[2]] = Number.parseFloat(elem[1]); 397 | var res = elem[2].split(' -> '); 398 | srcSet[res[0]] = 0; 399 | dstSet[res[1]] = 1; 400 | } 401 | srcList = keys(srcSet); 402 | dstList = keys(dstSet); 403 | console.log(dataDict); 404 | console.log(srcList); 405 | console.log(dstList); 406 | 407 | points = []; 408 | for(var i = 0; i < srcList.length; i++) { 409 | for(var j = 0; j < dstList.length; j++) { 410 | var k = srcList[i] + ' -> ' + dstList[j]; 411 | if(dataDict[k]) { 412 | var conf = dataDict[k]; 413 | points.push({x: j, y: i, conf: conf}); 414 | } 415 | } 416 | } 417 | 418 | var padding = {left: 50, right: 0, top: 0, bottom: 20}; 419 | var maxRadius = 15; 420 | var svg = d3.select('#dist-svg'); 421 | var width = svg.attr("width") - padding.left - padding.right; 422 | var height = svg.attr("height") - padding.top - padding.bottom; 423 | 424 | var xScale = d3.scale.ordinal() 425 | .domain(d3.range(dstList.length)) 426 | .rangeRoundBands([0, width]); 427 | var yScale = d3.scale.ordinal() 428 | .domain(d3.range(srcList.length)) 429 | .rangeRoundBands([0, height]); 430 | 431 | var hLine = svg.selectAll(".line") 432 | .data(srcList) 433 | .enter() 434 | .append("line") 435 | .attr('x1', xScale(0) + xScale.rangeBand() / 2) 436 | .attr('x2', xScale(dstList.length - 1) + xScale.rangeBand() / 2) 437 | .attr('y1', function(d, i) { 438 | return height - yScale(i) - yScale.rangeBand() / 2; 439 | }) 440 | .attr('y2', function(d, i) { 441 | return height - yScale(i) - yScale.rangeBand() / 2; 442 | }) 443 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 444 | .attr('stroke', '#ccc') 445 | .attr('stroke-dasharray', '5,5'); 446 | 447 | var vLines = svg.selectAll(".line") 448 | .data(dstList) 449 | .enter() 450 | .append("line") 451 | .attr('x1', function(d,i){ 452 | return xScale(i) + xScale.rangeBand() / 2; 453 | }) 454 | .attr('x2', function(d,i){ 455 | return xScale(i) + xScale.rangeBand() / 2; 456 | }) 457 | .attr('y1', yScale(0) + yScale.rangeBand() / 2) 458 | .attr('y2', yScale(srcList.length - 1) + yScale.rangeBand() / 2) 459 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 460 | .attr('stroke', '#ccc') 461 | .attr('stroke-dasharray', '5,5'); 462 | 463 | var circles = svg.selectAll('.circle') 464 | .data(points) 465 | .enter() 466 | .append("circle") 467 | .attr('cx', function(d) { 468 | return xScale(d.x) + xScale.rangeBand() / 2; 469 | }) 470 | .attr('cy', function(d) { 471 | console.log(d, yScale(d.y), srcList.length); 472 | return height - yScale(d.y) - yScale.rangeBand() / 2; 473 | 474 | }) 475 | .attr('r', function(d) { 476 | return d.conf * maxRadius; 477 | }) 478 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 479 | .attr('fill', function(d) { 480 | return labelToColor(d.x + d.y); 481 | }); 482 | 483 | 484 | var xTexts = svg.selectAll(".label") 485 | .data(dstList) 486 | .enter() 487 | .append("text") 488 | .attr("x", function(d,i){ 489 | return xScale(i) + xScale.rangeBand() / 2; 490 | } ) 491 | .attr("y", height) 492 | .attr("dx", -15) 493 | .attr("dy", 0) 494 | .text(function(d){ 495 | return d; 496 | }) 497 | .attr("transform","translate(" + padding.left + "," + padding.top + ")") 498 | .attr('fill', 'black'); 499 | 500 | var yTexts = svg.selectAll(".label") 501 | .data(srcList) 502 | .enter() 503 | .append("text") 504 | .attr("x", 0) 505 | .attr("y", function(d, i) { 506 | return height - yScale(i) - yScale.rangeBand() / 2; 507 | }) 508 | .attr("dx", 0) 509 | .attr("dy", 0) 510 | .text(function(d){ 511 | return d; 512 | }) 513 | .attr("transform","translate(0," + padding.top + ")") 514 | .attr('fill', 'black'); 515 | 516 | 517 | } 518 | 519 | getResult(); 520 | }); -------------------------------------------------------------------------------- /doc/diag/entire-arch-0.fem: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | D73A4816-68C7-4831-9C71-A30987EF5958 11 | FreeModel_1 12 | FreeModel_1 13 | 1464519823 14 | asus 15 | 1464519823 16 | asus 17 | [ModelOptions] 18 | 19 | [ModelOptions\Free model options] 20 | CaseSensitive=No 21 | DisplayName=Yes 22 | EnableTrans=No 23 | EnableRequirements=No 24 | 25 | [ModelOptions\Free model options\NamingOptionsTemplates] 26 | 27 | [ModelOptions\Free model options\ClssNamingOptions] 28 | 29 | [ModelOptions\Free model options\ClssNamingOptions\FRMPCKG] 30 | 31 | [ModelOptions\Free model options\ClssNamingOptions\FRMPCKG\Name] 32 | Template= 33 | MaxLen=254 34 | Case=M 35 | ValidChar= 36 | InvldChar= 37 | AllValid=Yes 38 | NoAccent=No 39 | DefaultChar= 40 | Script= 41 | ConvTable= 42 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 43 | 44 | [ModelOptions\Free model options\ClssNamingOptions\FRMPCKG\Code] 45 | Template= 46 | MaxLen=254 47 | Case=M 48 | ValidChar= 49 | InvldChar= 50 | AllValid=Yes 51 | NoAccent=No 52 | DefaultChar= 53 | Script= 54 | ConvTable= 55 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 56 | 57 | [ModelOptions\Free model options\ClssNamingOptions\FILO] 58 | 59 | [ModelOptions\Free model options\ClssNamingOptions\FILO\Name] 60 | Template= 61 | MaxLen=254 62 | Case=M 63 | ValidChar= 64 | InvldChar= 65 | AllValid=Yes 66 | NoAccent=No 67 | DefaultChar= 68 | Script= 69 | ConvTable= 70 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 71 | 72 | [ModelOptions\Free model options\ClssNamingOptions\FILO\Code] 73 | Template= 74 | MaxLen=254 75 | Case=M 76 | ValidChar= 77 | InvldChar= 78 | AllValid=Yes 79 | NoAccent=No 80 | DefaultChar= 81 | Script= 82 | ConvTable= 83 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 84 | 85 | [ModelOptions\Free model options\ClssNamingOptions\FRMEOBJ] 86 | 87 | [ModelOptions\Free model options\ClssNamingOptions\FRMEOBJ\Name] 88 | Template= 89 | MaxLen=254 90 | Case=M 91 | ValidChar= 92 | InvldChar= 93 | AllValid=Yes 94 | NoAccent=No 95 | DefaultChar= 96 | Script= 97 | ConvTable= 98 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 99 | 100 | [ModelOptions\Free model options\ClssNamingOptions\FRMEOBJ\Code] 101 | Template= 102 | MaxLen=254 103 | Case=M 104 | ValidChar= 105 | InvldChar= 106 | AllValid=Yes 107 | NoAccent=No 108 | DefaultChar= 109 | Script= 110 | ConvTable= 111 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 112 | 113 | [ModelOptions\Free model options\ClssNamingOptions\FRMELNK] 114 | 115 | [ModelOptions\Free model options\ClssNamingOptions\FRMELNK\Name] 116 | Template= 117 | MaxLen=254 118 | Case=M 119 | ValidChar= 120 | InvldChar= 121 | AllValid=Yes 122 | NoAccent=No 123 | DefaultChar= 124 | Script= 125 | ConvTable= 126 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 127 | 128 | [ModelOptions\Free model options\ClssNamingOptions\FRMELNK\Code] 129 | Template= 130 | MaxLen=254 131 | Case=M 132 | ValidChar= 133 | InvldChar= 134 | AllValid=Yes 135 | NoAccent=No 136 | DefaultChar= 137 | Script= 138 | ConvTable= 139 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 140 | 141 | [ModelOptions\Free model options\ClssNamingOptions\DefaultClass] 142 | 143 | [ModelOptions\Free model options\ClssNamingOptions\DefaultClass\Name] 144 | Template= 145 | MaxLen=254 146 | Case=M 147 | ValidChar= 148 | InvldChar= 149 | AllValid=Yes 150 | NoAccent=No 151 | DefaultChar= 152 | Script= 153 | ConvTable= 154 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 155 | 156 | [ModelOptions\Free model options\ClssNamingOptions\DefaultClass\Code] 157 | Template= 158 | MaxLen=254 159 | Case=M 160 | ValidChar= 161 | InvldChar= 162 | AllValid=Yes 163 | NoAccent=No 164 | DefaultChar= 165 | Script= 166 | ConvTable= 167 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 168 | 169 | 170 | 69272F07-0C28-4600-8120-5E662E697467 171 | Diagram_1 172 | Diagram_1 173 | 1464519823 174 | asus 175 | 1464520106 176 | asus 177 | [DisplayPreferences] 178 | 179 | [DisplayPreferences\FRM] 180 | 181 | [DisplayPreferences\General] 182 | Adjust to text=Yes 183 | Snap Grid=No 184 | Constrain Labels=Yes 185 | Display Grid=No 186 | Show Page Delimiter=Yes 187 | Grid size=0 188 | Graphic unit=2 189 | Window color=255, 255, 255 190 | Background image= 191 | Background mode=8 192 | Watermark image= 193 | Watermark mode=8 194 | Show watermark on screen=No 195 | Gradient mode=0 196 | Gradient end color=255, 255, 255 197 | Show Swimlane=No 198 | SwimlaneVert=Yes 199 | TreeVert=No 200 | CompDark=0 201 | 202 | [DisplayPreferences\Object] 203 | Mode=2 204 | Trunc Length=40 205 | Word Length=40 206 | Word Text=!""#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 207 | Shortcut IntIcon=Yes 208 | Shortcut IntLoct=Yes 209 | Shortcut IntFullPath=No 210 | Shortcut IntLastPackage=Yes 211 | Shortcut ExtIcon=Yes 212 | Shortcut ExtLoct=No 213 | Shortcut ExtFullPath=No 214 | Shortcut ExtLastPackage=Yes 215 | Shortcut ExtIncludeModl=Yes 216 | EObjShowStrn=Yes 217 | ExtendedObject.Comment=No 218 | ExtendedObject.IconPicture=No 219 | ExtendedObject_SymbolLayout=<Form>[CRLF] <StandardAttribute Name="Stereotype" Attribute="Stereotype" Prefix="&lt;&lt;" Suffix="&gt;&gt;" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Object Name" Attribute="DisplayName" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="Yes" />[CRLF] <Separator Name="Separator" />[CRLF] <StandardAttribute Name="Comment" Attribute="Comment" Prefix="" Suffix="" Alignment="LEFT" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Icon" Attribute="IconPicture" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="Yes" />[CRLF]</Form> 220 | ELnkShowStrn=Yes 221 | ELnkShowName=Yes 222 | ExtendedLink_SymbolLayout=<Form>[CRLF] <Form Name="Center" >[CRLF] <StandardAttribute Name="Stereotype" Attribute="Stereotype" Prefix="&lt;&lt;" Suffix="&gt;&gt;" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Name" Attribute="DisplayName" Prefix="" Suffix="" Caption="" Mandatory="No" />[CRLF] </Form>[CRLF] <Form Name="Source" >[CRLF] </Form>[CRLF] <Form Name="Destination" >[CRLF] </Form>[CRLF]</Form> 223 | FileObject.Stereotype=No 224 | FileObject.DisplayName=Yes 225 | FileObject.LocationOrName=No 226 | FileObject.IconPicture=No 227 | FileObject.IconMode=Yes 228 | FileObject_SymbolLayout=<Form>[CRLF] <StandardAttribute Name="Stereotype" Attribute="Stereotype" Prefix="&lt;&lt;" Suffix="&gt;&gt;" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] <ExclusiveChoice Name="Exclusive Choice" Mandatory="Yes" Display="HorizontalRadios" >[CRLF] <StandardAttribute Name="Name" Attribute="DisplayName" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Location" Attribute="LocationOrName" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] </ExclusiveChoice>[CRLF] <StandardAttribute Name="Icon" Attribute="IconPicture" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="Yes" />[CRLF]</Form> 229 | PckgShowStrn=Yes 230 | Package.Comment=No 231 | Package.IconPicture=No 232 | Package_SymbolLayout= 233 | Display Model Version=Yes 234 | 235 | [DisplayPreferences\Symbol] 236 | 237 | [DisplayPreferences\Symbol\FRMEOBJ] 238 | STRNFont=新宋体,8,N 239 | STRNFont color=0, 0, 0 240 | DISPNAMEFont=新宋体,8,N 241 | DISPNAMEFont color=0, 0, 0 242 | LABLFont=新宋体,8,N 243 | LABLFont color=0, 0, 0 244 | AutoAdjustToText=Yes 245 | Keep aspect=No 246 | Keep center=No 247 | Keep size=No 248 | Width=6000 249 | Height=2000 250 | Brush color=255 255 255 251 | Fill Color=Yes 252 | Brush style=6 253 | Brush bitmap mode=12 254 | Brush gradient mode=64 255 | Brush gradient color=192 192 192 256 | Brush background image= 257 | Custom shape= 258 | Custom text mode=0 259 | Pen=1 0 255 128 128 260 | Shadow color=192 192 192 261 | Shadow=0 262 | 263 | [DisplayPreferences\Symbol\FRMELNK] 264 | CENTERFont=新宋体,8,N 265 | CENTERFont color=0, 0, 0 266 | Line style=1 267 | AutoAdjustToText=Yes 268 | Keep aspect=No 269 | Keep center=No 270 | Keep size=No 271 | Brush color=255 255 255 272 | Fill Color=Yes 273 | Brush style=1 274 | Brush bitmap mode=12 275 | Brush gradient mode=0 276 | Brush gradient color=118 118 118 277 | Brush background image= 278 | Custom shape= 279 | Custom text mode=0 280 | Pen=1 0 128 128 255 281 | Shadow color=192 192 192 282 | Shadow=0 283 | 284 | [DisplayPreferences\Symbol\FILO] 285 | OBJSTRNFont=新宋体,8,N 286 | OBJSTRNFont color=0, 0, 0 287 | DISPNAMEFont=新宋体,8,N 288 | DISPNAMEFont color=0, 0, 0 289 | LCNMFont=新宋体,8,N 290 | LCNMFont color=0, 0, 0 291 | AutoAdjustToText=Yes 292 | Keep aspect=No 293 | Keep center=No 294 | Keep size=No 295 | Width=4800 296 | Height=3600 297 | Brush color=255 255 255 298 | Fill Color=Yes 299 | Brush style=1 300 | Brush bitmap mode=12 301 | Brush gradient mode=0 302 | Brush gradient color=118 118 118 303 | Brush background image= 304 | Custom shape= 305 | Custom text mode=0 306 | Pen=1 0 0 0 255 307 | Shadow color=192 192 192 308 | Shadow=0 309 | 310 | [DisplayPreferences\Symbol\FRMPCKG] 311 | STRNFont=新宋体,8,N 312 | STRNFont color=0, 0, 0 313 | DISPNAMEFont=新宋体,8,N 314 | DISPNAMEFont color=0, 0, 0 315 | LABLFont=新宋体,8,N 316 | LABLFont color=0, 0, 0 317 | AutoAdjustToText=Yes 318 | Keep aspect=No 319 | Keep center=No 320 | Keep size=No 321 | Width=4800 322 | Height=3600 323 | Brush color=255 255 192 324 | Fill Color=Yes 325 | Brush style=6 326 | Brush bitmap mode=12 327 | Brush gradient mode=65 328 | Brush gradient color=255 255 255 329 | Brush background image= 330 | Custom shape= 331 | Custom text mode=0 332 | Pen=1 0 178 178 178 333 | Shadow color=192 192 192 334 | Shadow=0 335 | 336 | [DisplayPreferences\Symbol\USRDEPD] 337 | OBJXSTRFont=新宋体,8,N 338 | OBJXSTRFont color=0, 0, 0 339 | Line style=1 340 | AutoAdjustToText=Yes 341 | Keep aspect=No 342 | Keep center=No 343 | Keep size=No 344 | Brush color=255 255 255 345 | Fill Color=Yes 346 | Brush style=1 347 | Brush bitmap mode=12 348 | Brush gradient mode=0 349 | Brush gradient color=118 118 118 350 | Brush background image= 351 | Custom shape= 352 | Custom text mode=0 353 | Pen=2 0 128 128 255 354 | Shadow color=192 192 192 355 | Shadow=0 356 | 357 | [DisplayPreferences\Symbol\Free Symbol] 358 | Free TextFont=新宋体,8,N 359 | Free TextFont color=0, 0, 0 360 | Line style=0 361 | AutoAdjustToText=Yes 362 | Keep aspect=No 363 | Keep center=No 364 | Keep size=No 365 | Brush color=255 255 255 366 | Fill Color=Yes 367 | Brush style=1 368 | Brush bitmap mode=12 369 | Brush gradient mode=0 370 | Brush gradient color=118 118 118 371 | Brush background image= 372 | Custom shape= 373 | Custom text mode=0 374 | Pen=1 0 0 0 255 375 | Shadow color=192 192 192 376 | Shadow=0 377 | (8268, 11693) 378 | ((315,354), (433,354)) 379 | 1 380 | 15 381 | 382 | 383 | 1464520073 384 | 1464520096 385 | ((-23820,18101), (-7546,6927)) 386 | 4130 387 | 0 388 | 0 389 | 3 390 | 16777215 391 | 12632256 392 | 新宋体,8,N 393 | 1 394 | 395 | 396 | 1464519970 397 | 1464520035 398 | ((-11520,9900), (-11055,14925)) 399 | ((-11250,9900),(-11325,14925)) 400 | 0 401 | 1 402 | 0 403 | 12632256 404 | 新宋体,8,N 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 1464519972 414 | 1464520037 415 | ((-19875,9525), (-11700,15075)) 416 | ((-11700,9525),(-19875,15075)) 417 | 0 418 | 1 419 | 0 420 | 12632256 421 | 新宋体,8,N 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 1464519975 431 | 1464520032 432 | ((-8850,9260), (4275,9716)) 433 | ((-8850,9450),(4275,9525)) 434 | 0 435 | 1 436 | 0 437 | 12632256 438 | 新宋体,8,N 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 1464519979 448 | 1464520038 449 | ((-11625,-3675), (-11175,8775)) 450 | ((-11400,-3675),(-11400,8775)) 451 | 0 452 | 1 453 | 0 454 | 12632256 455 | 新宋体,8,N 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 1464519982 465 | 1464520039 466 | ((-20325,-3600), (-19875,8550)) 467 | ((-20100,-3600),(-20100,8550)) 468 | 0 469 | 1 470 | 0 471 | 12632256 472 | 新宋体,8,N 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 1464519983 482 | 1464520041 483 | ((-9150,-4350), (4125,8775)) 484 | ((-9150,-4350),(4125,8775)) 485 | 0 486 | 1 487 | 0 488 | 12632256 489 | 新宋体,8,N 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | Web 499 | 1464519831 500 | 1464519887 501 | ((-14400,11175), (-7950,7650)) 502 | 4130 503 | 0 504 | 0 505 | 16777215 506 | 12632256 507 | 新宋体,8,N 508 | 509 | 510 | DB 511 | 1464519889 512 | 1464519896 513 | ((-14550,16838), (-8100,13313)) 514 | 4130 515 | 0 516 | 0 517 | 16777215 518 | 12632256 519 | 新宋体,8,N 520 | 521 | 522 | 邮件服务 523 | 1464519898 524 | 1464520005 525 | ((-23100,16913), (-16650,13388)) 526 | 4130 527 | 0 528 | 0 529 | 16777215 530 | 12632256 531 | 新宋体,8,N 532 | 533 | 534 | CDN 535 | 1464519905 536 | 1464519913 537 | ((-23175,11213), (-16725,7688)) 538 | 4130 539 | 0 540 | 0 541 | 16777215 542 | 12632256 543 | 新宋体,8,N 544 | 545 | 546 | RMP 547 | 1464519913 548 | 1464519938 549 | ((-1199,16763), (12299,7727)) 550 | 4130 551 | 0 552 | 0 553 | 16777215 554 | 12632256 555 | 新宋体,8,N 556 | 1 557 | 558 | 559 | 浏览器 560 | 1464519923 561 | 1464519999 562 | ((-22949,-2587), (-8025,-6113)) 563 | 4130 564 | 0 565 | 0 566 | 16777215 567 | 12632256 568 | 新宋体,8,N 569 | 1 570 | 571 | 572 | 数据挖掘平台 573 | 1464520106 574 | 1464520125 575 | ((-23847,18341), (-19048,19706)) 576 | 4130 577 | 0 578 | 16777215 579 | 16777215 580 | 12632256 581 | 新宋体,8,N 582 | 1 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | -------------------------------------------------------------------------------- /req_handlers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from flask import request, make_response 4 | import re 5 | import os 6 | import config 7 | import urllib2 8 | import time 9 | from threading import Thread 10 | import dm 11 | 12 | import sys 13 | reload(sys) 14 | sys.setdefaultencoding('utf-8') 15 | 16 | import json 17 | json.stringify = json.dumps 18 | json.parse = json.loads 19 | 20 | def index(): 21 | return 'Hello, Flask!' 22 | 23 | def isAssoc(algo): 24 | return algo in ['apriori'] 25 | 26 | def isClassify(algo): 27 | return algo in ['naive_bayes', 'knn', 'svm'] 28 | 29 | def isCluster(algo): 30 | return algo in ['kmeans', 'kmedoids'] 31 | 32 | """ 33 | 参数: 34 | cols:列名称的列表 35 | rows:记录的偏移(可选)及数量 36 | algo:所使用的算法 37 | args:算法所需的参数,格式为json 38 | """ 39 | def mining(uid, token, proj, rsrc): 40 | 41 | res = make_response() 42 | res.headers['Content-Type'] = "application/json" 43 | 44 | #获取参数 45 | for e in [token, proj, rsrc]: 46 | if not re.match(r'^\w+$', e): 47 | res.data = json.stringify({'succ': False, 'msg': 'Rsrc invalid!'}) 48 | return res 49 | 50 | # title 51 | title = request.form.get('title') 52 | if not title: 53 | res.data = json.stringify({'succ': False, 'msg': 'No title!'}) 54 | return res 55 | 56 | # cols=["col0","col1","col2", ...] 57 | cols = request.form.get('cols') 58 | if cols: 59 | cols = json.parse(cols) 60 | assert isinstance(cols, list) 61 | else: 62 | cols = [] 63 | 64 | # start 65 | start = request.form.get('start') 66 | if start: 67 | start = int(start) 68 | else: 69 | start = 0 70 | 71 | # count 72 | count = request.form.get('count') 73 | if count: 74 | count = int(count) 75 | end = start + count 76 | else: 77 | end = None 78 | 79 | algo = request.form.get('algo') 80 | 81 | args = request.form.get('args') 82 | print args 83 | if args: 84 | args = json.parse(args) 85 | assert isinstance(args, dict) 86 | else: 87 | args = {} 88 | # TODO: filter args 89 | 90 | context = { 91 | "user": uid, 92 | "title": title, 93 | "rsrc": token + '/' + proj + '/' + rsrc, 94 | "cols": cols, 95 | "start": start, 96 | "end": end, 97 | "algo": algo, 98 | "args": args, 99 | } 100 | 101 | if isClassify(algo): 102 | # predictStart 103 | predictStart = request.form.get('predictStart') 104 | if predictStart: 105 | predictStart = int(predictStart) 106 | else: 107 | predictStart = 0 108 | 109 | # predictCount 110 | predictCount = request.form.get('predictCount') 111 | if predictCount: 112 | predictCount = int(predictCount) 113 | predictEnd = predictStart + predictCount 114 | else: 115 | predictEnd = None 116 | 117 | label = request.form.get('label') 118 | if label is None: label = "" 119 | if not re.match(r'^\w+$', label): 120 | return json.stringify({'succ': False, 'msg': 'Label invalid!'}) 121 | 122 | context['predictStart'] = predictStart 123 | context['predictEnd'] = predictEnd 124 | context['label'] = label 125 | 126 | if not isAssoc(algo): 127 | absence = request.form.get('absence') 128 | fillval = request.form.get('fillval') 129 | if fillval is None: fillval = 0 130 | formal = request.form.get('formal') 131 | distinct = request.form.get('distinct') == 'true' 132 | 133 | context['absence'] = absence 134 | context['fillval'] = fillval 135 | context['formal'] = formal 136 | context['distinct'] = distinct 137 | 138 | 139 | 140 | # 调用具体算法 141 | funcDict = { 142 | "kmeans": kmeans, 143 | "kmedoids": kmedoids, 144 | "apriori": apriori, 145 | "naive_bayes": classify, 146 | "knn": classify, 147 | "svm": classify 148 | } 149 | func = funcDict.get(algo) 150 | if not func: 151 | res.data = json.stringify({'succ': False, 'msg': 'Unknown algo!'}) 152 | return res 153 | 154 | Thread(target=func, args=(context,)).start(); 155 | 156 | res.data = json.stringify({'succ': True, 'msg': 'Done...'}) 157 | return res 158 | 159 | def preprocess(data, context): 160 | 161 | absence = context['absence'] 162 | if absence == 'rm': 163 | data = dm.removeAbsence(data) 164 | elif absence == 'val': 165 | data = dm.fillAbsenceWithVal(data, context['fillval']) 166 | elif absence == 'avg': 167 | data = dm.fillAbsenceWithAvg(data) 168 | 169 | formal = context['formal'] 170 | if formal == 'maxmin': 171 | data = dm.maxMinRestrict(data) 172 | elif formal == 'zscore': 173 | data = dm.zScoreRestrict(data) 174 | elif formal == 'demical': 175 | data = dm.demicalRestrict(data) 176 | 177 | return data 178 | 179 | def apriori(context): 180 | rawData = getDataFromSvr(context['rsrc']) 181 | _, data = processData(rawData, context['start'], \ 182 | context['end'], context['cols']) 183 | dataList = convertDataToArr(data) 184 | 185 | rawRes = dm.apriori(dataList, **context['args']) 186 | 187 | conn = config.getConn() 188 | cursor = conn.cursor() 189 | hid = dbAddHistory(cursor, context, 'assoc') 190 | result = [] 191 | count = 0 192 | for row in rawRes: 193 | v = "{0} -> {1}".format( 194 | ', '.join(row[0]), 195 | ', '.join(row[1]) 196 | ) 197 | result.append((hid, count, row[2], v, row[3], row[4])) 198 | count += 1 199 | dbWriteBackAssoc(cursor, result) 200 | dbAddMessage(cursor, context, hid) 201 | try: sendMessageByEmail(cursor, context, hid) 202 | except Exception: pass 203 | 204 | conn.commit() 205 | cursor.close() 206 | conn.close() 207 | return json.stringify({'succ': True, 'msg': 'Done...'}) 208 | 209 | def kmedoids(context): 210 | rawData = getDataFromSvr(context['rsrc']) 211 | if(context['distinct']): 212 | rawData = dm.distinct(rawData) 213 | idList, data = processData(rawData, context['start'], \ 214 | context['end'], context['cols']) 215 | dataList = convertDataToArr(data) 216 | dataList = preprocess(dataList, context) 217 | 218 | _, _, rawRes = dm.kmedoids(dataList, **context['args']) 219 | 220 | conn = config.getConn() 221 | cursor = conn.cursor() 222 | hid = dbAddHistory(cursor, context, 'cluster') 223 | result = [] 224 | clusterId = 0 225 | for medoid in rawRes.keys(): 226 | for i in rawRes[medoid]: 227 | result.append((hid, idList[i], clusterId, 228 | json.stringify(dataList[i]))) 229 | clusterId += 1 230 | 231 | dbWriteBack(cursor, result) 232 | dbAddMessage(cursor, context, hid) 233 | try: sendMessageByEmail(cursor, context, hid) 234 | except Exception: pass 235 | 236 | conn.commit() 237 | cursor.close() 238 | conn.close() 239 | return json.stringify({'succ': True, 'msg': 'Done...'}) 240 | 241 | def kmeans(context): 242 | rawData = getDataFromSvr(context['rsrc']) 243 | if(context['distinct']): 244 | rawData = dm.distinct(rawData) 245 | idList, data = processData(rawData, context['start'], \ 246 | context['end'], context['cols']) 247 | dataList = convertDataToArr(data) 248 | dataList = preprocess(dataList, context) 249 | 250 | from sklearn.cluster import KMeans 251 | clf = KMeans(**context['args']) 252 | clf.fit(dataList) 253 | 254 | conn = config.getConn() 255 | cursor = conn.cursor() 256 | hid = dbAddHistory(cursor, context, 'cluster') 257 | result = [] 258 | for i in xrange(len(clf.labels_)): 259 | result.append((hid, idList[i], clf.labels_[i], 260 | json.stringify(data[i]))) 261 | 262 | dbWriteBack(cursor, result) 263 | dbAddMessage(cursor, context, hid) 264 | try: sendMessageByEmail(cursor, context, hid) 265 | except Exception: pass 266 | 267 | conn.commit() 268 | cursor.close() 269 | conn.close() 270 | return json.stringify({'succ': True, 'msg': 'Done...'}) 271 | 272 | def classify(context): 273 | 274 | from sklearn.neighbors import KNeighborsClassifier 275 | from sklearn.naive_bayes import MultinomialNB 276 | from sklearn.svm import SVC 277 | 278 | label = context['label'] 279 | algo = context['algo'] 280 | if algo == 'svm': 281 | classifier = SVC 282 | elif algo == 'knn': 283 | classifier = KNeighborsClassifier 284 | elif algo == 'naive_bayes': 285 | classifier = MultinomialNB 286 | else: 287 | assert False 288 | args = context['args'] 289 | for k in args: 290 | if isinstance(args[k], unicode): 291 | args[k] = str(args[k]) 292 | 293 | rawData = getDataFromSvr(context['rsrc']) 294 | if(context['distinct']): 295 | rawData = dm.distinct(rawData) 296 | labelList, train = getTrainingSet(rawData, label, context['start'], \ 297 | context['end'], context['cols']) 298 | trainList = convertDataToArr(train) 299 | trainList = preprocess(trainList, context) 300 | idList, predict = getPredictSet(rawData, context['predictStart'], \ 301 | context['predictEnd'], context['cols']) 302 | predictList = convertDataToArr(predict) 303 | predictList = preprocess(predictList, context) 304 | 305 | clf = classifier(**args) 306 | clf.fit(trainList, labelList) 307 | rawRes = clf.predict(predictList) 308 | 309 | conn = config.getConn() 310 | cursor = conn.cursor() 311 | id = dbAddHistory(cursor, context, 'classify') 312 | 313 | result = [] 314 | for i in xrange(len(rawRes)): 315 | result.append((id, idList[i], rawRes[i], json.stringify(predict[i]))) 316 | 317 | dbWriteBack(cursor, result) 318 | dbAddMessage(cursor, context, id) 319 | try: sendMessageByEmail(cursor, context, hid) 320 | except Exception: pass 321 | 322 | conn.commit() 323 | cursor.close() 324 | conn.close() 325 | return json.stringify({'succ': True, 'msg': 'Done...'}) 326 | 327 | def dbAddMessage(cursor, context, hid): 328 | content = "您提交的任务已完成,资源:{0},ID:{1}。".format(context['rsrc'], hid); 329 | sql = 'insert into message (userid, content, tm) values (%s, %s, null)' 330 | cursor.execute(sql, (context['user'], content)) 331 | 332 | def dbAddHistory(cursor, context, type): 333 | sql = 'insert into history (userid, title, rsrc, tp, tm) values (%s, %s, %s, %s, null)' 334 | cursor.execute(sql, (context['user'], context['title'], context['rsrc'], type)) 335 | return cursor.lastrowid 336 | 337 | def dbWriteBack(cursor, result): 338 | sql = "insert into result (hid, id, res1, res2) values (%s,%s,%s,%s)" 339 | cursor.executemany(sql, result) 340 | 341 | def dbWriteBackAssoc(cursor, result): 342 | sql = "insert into result (hid, id, res1, res2, res3, res4) values (%s,%s,%s,%s,%s,%s)" 343 | cursor.executemany(sql, result) 344 | 345 | def getDataFromSvr(rsrc): 346 | url = config.rmp + '/Entity/' + rsrc + '/' 347 | jsonStr = urllib2.urlopen(urllib2.Request(url)).read().decode('utf-8') 348 | return json.parse(jsonStr)[rsrc.split('/')[-1]] 349 | 350 | def convertData(data, start = 0, end = None, cols = [], label = None): 351 | """ 352 | 将对象数组转化为二维数组, 353 | 将id单独拿出来存为数组, 354 | 如有标签将其去除, 355 | 最后将数组切片。 356 | """ 357 | 358 | idList = [] 359 | dataList = [] 360 | labelList = [] 361 | for elem in data: 362 | elemId = elem['id'] 363 | idList.append(elemId) 364 | del elem['id'] 365 | 366 | if(label): 367 | elemLabel = elem[label] 368 | labelList.append(elemLabel) 369 | del elem[label] 370 | 371 | row = [] 372 | for k, v in elem.items(): 373 | if (v != None and v != "") and \ 374 | (len(cols) == 0 or k in cols): 375 | row.append(v) 376 | dataList.append(row) 377 | 378 | elem['id'] = elemId 379 | if(label): elem[label] = elemLabel 380 | 381 | return idList[start:end], \ 382 | dataList[start:end], labelList[start:end] 383 | 384 | def processData(rawData, start = 0, end = None, cols = []): 385 | data = rawData[start:end] 386 | 387 | idList = [] 388 | for i in xrange(len(data)): 389 | elem = dict(data[i]) 390 | idList.append(elem['id']) 391 | del elem['id'] 392 | for k, v in elem.items(): 393 | if len(cols) != 0 and k not in cols: 394 | del elem[k] 395 | data[i] = elem 396 | return idList, data 397 | 398 | getPredictSet = processData 399 | 400 | def getTrainingSet(rawData, label, start = 0, end = None, cols = []): 401 | data = rawData[start:end] 402 | labelList = [] 403 | for i in xrange(len(data)): 404 | elem = dict(data[i]) 405 | del elem['id'] 406 | labelList.append(elem[label]) 407 | for k, v in elem.items(): 408 | if len(cols) != 0 and k not in cols: 409 | del elem[k] 410 | data[i] = elem 411 | return labelList, data 412 | 413 | def convertDataToArr(data): 414 | dataList = [] 415 | for elem in data: 416 | row = [] 417 | for v in elem.values(): 418 | row.append(v) 419 | dataList.append(row) 420 | return dataList 421 | 422 | def getData(context): 423 | rawData = getDataFromSvr(context['rsrc']) 424 | 425 | cols = context['cols'] 426 | start = context['start'] 427 | end = context['end'] 428 | idList, dataList, _ = convertData(rawData, start, end, cols) 429 | 430 | return idList, dataList 431 | 432 | def getDataWithLabel(context): 433 | rawData = getDataFromSvr(context['rsrc']) 434 | 435 | cols = context['cols'] 436 | start = context['start'] 437 | end = context['end'] 438 | predictStart = context['predictStart'] 439 | predictEnd = context['predictEnd'] 440 | label = context['label'] 441 | 442 | # 训练集 443 | _, dataList, labelList = convertData(rawData, start, end, cols, label) 444 | 445 | # 测试集 446 | idList, predictList, _ = convertData(rawData, predictStart, predictEnd, cols, label) 447 | 448 | return dataList, labelList, idList, predictList 449 | 450 | def getHistory(uid): 451 | return getHistoryById(uid, 0) 452 | 453 | # id=0时为全部 454 | def dbGetHistory(cur, uid, id): 455 | sql = "select id,rsrc,tp,tm,title from history where 1=1" 456 | args = [] 457 | if id != 0: 458 | sql += ' and id=%s' 459 | args.append(id) 460 | if uid != 0: 461 | sql += ' and userid=%s' 462 | args.append(uid) 463 | cur.execute(sql, tuple(args)) 464 | result = [] 465 | for row in cur.fetchall(): 466 | obj = { 467 | "id": row[0], 468 | "rsrc": row[1], 469 | "type": row[2], 470 | "time": str(row[3]), 471 | "title": row[4] 472 | } 473 | result.append(obj) 474 | return result 475 | 476 | # id=0时为全部 477 | def getHistoryById(uid, id): 478 | conn = config.getConn() 479 | cur = conn.cursor() 480 | result = dbGetHistory(cur, uid, id) 481 | cur.close() 482 | conn.close() 483 | res = make_response(json.stringify({"succ": True, "data": result})) 484 | res.headers["Content-Type"] = "application/json" 485 | return res 486 | 487 | def dbGetResult(cur, id): 488 | sql = "select id,res1,res2,res3,res4 from result where hid=%s" 489 | cur.execute(sql, (id,)) 490 | result = cur.fetchall() 491 | return result 492 | 493 | def getResultById(id): 494 | conn = config.getConn() 495 | cur = conn.cursor() 496 | result = dbGetResult(cur, id) 497 | cur.close() 498 | conn.close() 499 | res = make_response(json.stringify({"succ": True, "data": result})) 500 | return res 501 | 502 | def csvForm(s): 503 | s = str(s) 504 | if ',' in s: 505 | s = '"' + s.replace('"', '""') + '"' 506 | return s 507 | 508 | def generateCsvAssoc(data): 509 | from cStringIO import StringIO 510 | buffer = StringIO() 511 | headLine = ['rule', 'conf', 'frequent support', 'src support'] 512 | buffer.write(','.join(headLine)) 513 | buffer.write('\n') 514 | 515 | for row in data: 516 | line = map(csvForm, [row[2], row[1], row[3], row[4]]) 517 | buffer.write(','.join(line)) 518 | buffer.write('\n') 519 | 520 | return buffer.getvalue() 521 | 522 | def generateCsvOther(data): 523 | data = [list(row) for row in data] 524 | for row in data: 525 | row[2] = json.parse(row[2]) 526 | attrs = data[0][2].keys() 527 | 528 | from cStringIO import StringIO 529 | buffer = StringIO() 530 | 531 | headLine = [] 532 | headLine.append('id') 533 | for k in attrs: headLine.append(k) 534 | headLine.append('label') 535 | buffer.write(','.join(headLine)) 536 | buffer.write('\n') 537 | 538 | for row in data: 539 | line = [] 540 | line.append(str(row[0])) 541 | for k in attrs: line.append(str(row[2][k])) 542 | line.append(str(row[1])) 543 | line = map(csvForm, line) 544 | buffer.write(','.join(line)) 545 | buffer.write('\n') 546 | 547 | return buffer.getvalue() 548 | 549 | def getResultCsv(id): 550 | conn = config.getConn() 551 | cur = conn.cursor() 552 | history = dbGetHistory(cur, 0, id) 553 | data = dbGetResult(cur, id) 554 | cur.close() 555 | conn.close() 556 | 557 | if len(history) == 0: 558 | assert False 559 | history = history[0] 560 | 561 | if history['type'] == 'assoc': 562 | result = generateCsvAssoc(data) 563 | else: 564 | result = generateCsvOther(data) 565 | res = make_response(result) 566 | res.headers["Content-Type"] = "application/csv;charset=utf-8" 567 | res.headers["Content-Disposition"] = "attachment; filename=" + str(id) + ".csv" 568 | return res 569 | 570 | # isread=-1时为全部 571 | def getMessage(uid, isread): 572 | conn = config.getConn() 573 | cur = conn.cursor() 574 | sql = "select id,content,tm,isread from message where userid=%s" 575 | if isread == 1: 576 | sql += " and isread=1" 577 | elif isread == 0: 578 | sql += " and isread=0" 579 | sql += " order by id desc" 580 | cur.execute(sql, (uid,)) 581 | result = cur.fetchall() 582 | cur.close() 583 | conn.close() 584 | newResult = [] 585 | for row in result: 586 | obj = { 587 | "id": row[0], 588 | "content": row[1], 589 | "tm": str(row[2]), 590 | "isread": 1 if row[3] else 0 591 | } 592 | newResult.append(obj) 593 | return make_response(json.stringify({"succ": True, "data": newResult})) 594 | 595 | def getMessageUnread(uid): 596 | return getMessage(uid, 0) 597 | 598 | def getMessageAll(uid): 599 | return getMessage(uid, -1) 600 | 601 | # id=0 为全部 602 | def markMessage(uid, id): 603 | conn = config.getConn() 604 | cur = conn.cursor() 605 | sql = "update message set isread=1 where userid=%s" 606 | if id != 0: 607 | sql += " and id=" + str(id) 608 | cur.execute(sql, (uid,)) 609 | conn.commit() 610 | cur.close() 611 | conn.close() 612 | return make_response(json.stringify({"succ": True})) 613 | 614 | def markMessageAll(uid): 615 | return markMessage(uid, 0) 616 | 617 | def notify(uid): 618 | conn = config.getConn() 619 | cur = conn.cursor() 620 | sql = "select count(*) from message where userid=%s and isread=0" 621 | cur.execute(sql, (uid,)) 622 | num = cur.fetchall()[0][0] 623 | cur.close() 624 | conn.close() 625 | return make_response(json.stringify({"succ": True, "unread": num})) 626 | 627 | def sendEmail(sender, reciver, subject, content, type='plain'): 628 | import smtplib 629 | from email.mime.text import MIMEText 630 | 631 | msg = MIMEText(content, type, 'utf-8') 632 | msg['Subject'] = subject 633 | msg['From'] = sender 634 | msg['To'] = reciver 635 | 636 | smtp = smtplib.SMTP() 637 | smtp.connect(config.smtp['server']) 638 | smtp.starttls() 639 | smtp.login(config.smtp['un'], config.smtp['authcode']) 640 | smtp.sendmail(config.smtp['un'], reciver, msg.as_string()) 641 | smtp.quit() 642 | 643 | def setEmail(uid): 644 | email = request.form.get('email') 645 | if email is None: email = "" 646 | if not re.match(r'^[\w\-\.]+?@(\w+?\.)+?\w{2,4}$', email): 647 | return make_response(json.stringify({"succ": False, "msg": "Email format error!"})) 648 | conn = config.getConn() 649 | cur = conn.cursor() 650 | sql = "replace into email (userid, email) values (%s,%s)" 651 | cur.execute(sql, (uid, email)) 652 | conn.commit() 653 | cur.close() 654 | conn.close() 655 | return make_response(json.stringify({"succ": True})) 656 | 657 | def dbGetEmail(cur, uid): 658 | sql = "select email from email where userid=%s" 659 | cur.execute(sql, (uid,)) 660 | res = cur.fetchall() 661 | if len(res) == 0: 662 | email = "" 663 | else: 664 | email = res[0][0] 665 | return email 666 | 667 | def getEmail(uid): 668 | conn = config.getConn() 669 | cur = conn.cursor() 670 | email = dbGetEmail(cur, uid) 671 | conn.commit() 672 | cur.close() 673 | conn.close() 674 | return make_response(json.stringify({"succ": True, "data": email})) 675 | 676 | def sendMessageByEmail(cur, context, hid): 677 | email = dbGetEmail(cur, context['user']) 678 | if not email: return 679 | subject = "您提交的任务已完成,资源:{0},ID:{1}。".format(context['rsrc'], hid); 680 | url = os.path.join(config.host, 'history.html#' + str(hid)).replace('\\', '/') 681 | content = '点击这里访问。' 682 | sendEmail('test@rmp.com', email, subject, content, 'html') -------------------------------------------------------------------------------- /doc/diag/traditional-mvc-0.fem: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | FF765B56-0DF7-40A7-8680-AE8CE4CDFDB5 11 | FreeModel_1 12 | FreeModel_1 13 | 1464181320 14 | asus 15 | 1464181320 16 | asus 17 | [ModelOptions] 18 | 19 | [ModelOptions\Free model options] 20 | CaseSensitive=No 21 | DisplayName=Yes 22 | EnableTrans=No 23 | EnableRequirements=No 24 | 25 | [ModelOptions\Free model options\NamingOptionsTemplates] 26 | 27 | [ModelOptions\Free model options\ClssNamingOptions] 28 | 29 | [ModelOptions\Free model options\ClssNamingOptions\FRMPCKG] 30 | 31 | [ModelOptions\Free model options\ClssNamingOptions\FRMPCKG\Name] 32 | Template= 33 | MaxLen=254 34 | Case=M 35 | ValidChar= 36 | InvldChar= 37 | AllValid=Yes 38 | NoAccent=No 39 | DefaultChar= 40 | Script= 41 | ConvTable= 42 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 43 | 44 | [ModelOptions\Free model options\ClssNamingOptions\FRMPCKG\Code] 45 | Template= 46 | MaxLen=254 47 | Case=M 48 | ValidChar= 49 | InvldChar= 50 | AllValid=Yes 51 | NoAccent=No 52 | DefaultChar= 53 | Script= 54 | ConvTable= 55 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 56 | 57 | [ModelOptions\Free model options\ClssNamingOptions\FILO] 58 | 59 | [ModelOptions\Free model options\ClssNamingOptions\FILO\Name] 60 | Template= 61 | MaxLen=254 62 | Case=M 63 | ValidChar= 64 | InvldChar= 65 | AllValid=Yes 66 | NoAccent=No 67 | DefaultChar= 68 | Script= 69 | ConvTable= 70 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 71 | 72 | [ModelOptions\Free model options\ClssNamingOptions\FILO\Code] 73 | Template= 74 | MaxLen=254 75 | Case=M 76 | ValidChar= 77 | InvldChar= 78 | AllValid=Yes 79 | NoAccent=No 80 | DefaultChar= 81 | Script= 82 | ConvTable= 83 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 84 | 85 | [ModelOptions\Free model options\ClssNamingOptions\FRMEOBJ] 86 | 87 | [ModelOptions\Free model options\ClssNamingOptions\FRMEOBJ\Name] 88 | Template= 89 | MaxLen=254 90 | Case=M 91 | ValidChar= 92 | InvldChar= 93 | AllValid=Yes 94 | NoAccent=No 95 | DefaultChar= 96 | Script= 97 | ConvTable= 98 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 99 | 100 | [ModelOptions\Free model options\ClssNamingOptions\FRMEOBJ\Code] 101 | Template= 102 | MaxLen=254 103 | Case=M 104 | ValidChar= 105 | InvldChar= 106 | AllValid=Yes 107 | NoAccent=No 108 | DefaultChar= 109 | Script= 110 | ConvTable= 111 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 112 | 113 | [ModelOptions\Free model options\ClssNamingOptions\FRMELNK] 114 | 115 | [ModelOptions\Free model options\ClssNamingOptions\FRMELNK\Name] 116 | Template= 117 | MaxLen=254 118 | Case=M 119 | ValidChar= 120 | InvldChar= 121 | AllValid=Yes 122 | NoAccent=No 123 | DefaultChar= 124 | Script= 125 | ConvTable= 126 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 127 | 128 | [ModelOptions\Free model options\ClssNamingOptions\FRMELNK\Code] 129 | Template= 130 | MaxLen=254 131 | Case=M 132 | ValidChar= 133 | InvldChar= 134 | AllValid=Yes 135 | NoAccent=No 136 | DefaultChar= 137 | Script= 138 | ConvTable= 139 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 140 | 141 | [ModelOptions\Free model options\ClssNamingOptions\DefaultClass] 142 | 143 | [ModelOptions\Free model options\ClssNamingOptions\DefaultClass\Name] 144 | Template= 145 | MaxLen=254 146 | Case=M 147 | ValidChar= 148 | InvldChar= 149 | AllValid=Yes 150 | NoAccent=No 151 | DefaultChar= 152 | Script= 153 | ConvTable= 154 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 155 | 156 | [ModelOptions\Free model options\ClssNamingOptions\DefaultClass\Code] 157 | Template= 158 | MaxLen=254 159 | Case=M 160 | ValidChar= 161 | InvldChar= 162 | AllValid=Yes 163 | NoAccent=No 164 | DefaultChar= 165 | Script= 166 | ConvTable= 167 | ConvTablePath=%_HOME%\Resource Files\Conversion Tables 168 | 169 | 170 | 1D1278C5-DEBC-4663-95A5-244C785AC6B7 171 | Diagram_1 172 | Diagram_1 173 | 1464181321 174 | asus 175 | 1464181878 176 | asus 177 | [DisplayPreferences] 178 | 179 | [DisplayPreferences\FRM] 180 | 181 | [DisplayPreferences\General] 182 | Adjust to text=Yes 183 | Snap Grid=No 184 | Constrain Labels=Yes 185 | Display Grid=No 186 | Show Page Delimiter=Yes 187 | Grid size=0 188 | Graphic unit=2 189 | Window color=255, 255, 255 190 | Background image= 191 | Background mode=8 192 | Watermark image= 193 | Watermark mode=8 194 | Show watermark on screen=No 195 | Gradient mode=0 196 | Gradient end color=255, 255, 255 197 | Show Swimlane=No 198 | SwimlaneVert=Yes 199 | TreeVert=No 200 | CompDark=0 201 | 202 | [DisplayPreferences\Object] 203 | Mode=2 204 | Trunc Length=40 205 | Word Length=40 206 | Word Text=!""#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 207 | Shortcut IntIcon=Yes 208 | Shortcut IntLoct=Yes 209 | Shortcut IntFullPath=No 210 | Shortcut IntLastPackage=Yes 211 | Shortcut ExtIcon=Yes 212 | Shortcut ExtLoct=No 213 | Shortcut ExtFullPath=No 214 | Shortcut ExtLastPackage=Yes 215 | Shortcut ExtIncludeModl=Yes 216 | EObjShowStrn=Yes 217 | ExtendedObject.Comment=No 218 | ExtendedObject.IconPicture=No 219 | ExtendedObject_SymbolLayout=<Form>[CRLF] <StandardAttribute Name="Stereotype" Attribute="Stereotype" Prefix="&lt;&lt;" Suffix="&gt;&gt;" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Object Name" Attribute="DisplayName" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="Yes" />[CRLF] <Separator Name="Separator" />[CRLF] <StandardAttribute Name="Comment" Attribute="Comment" Prefix="" Suffix="" Alignment="LEFT" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Icon" Attribute="IconPicture" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="Yes" />[CRLF]</Form> 220 | ELnkShowStrn=Yes 221 | ELnkShowName=Yes 222 | ExtendedLink_SymbolLayout=<Form>[CRLF] <Form Name="Center" >[CRLF] <StandardAttribute Name="Stereotype" Attribute="Stereotype" Prefix="&lt;&lt;" Suffix="&gt;&gt;" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Name" Attribute="DisplayName" Prefix="" Suffix="" Caption="" Mandatory="No" />[CRLF] </Form>[CRLF] <Form Name="Source" >[CRLF] </Form>[CRLF] <Form Name="Destination" >[CRLF] </Form>[CRLF]</Form> 223 | FileObject.Stereotype=No 224 | FileObject.DisplayName=Yes 225 | FileObject.LocationOrName=No 226 | FileObject.IconPicture=No 227 | FileObject.IconMode=Yes 228 | FileObject_SymbolLayout=<Form>[CRLF] <StandardAttribute Name="Stereotype" Attribute="Stereotype" Prefix="&lt;&lt;" Suffix="&gt;&gt;" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] <ExclusiveChoice Name="Exclusive Choice" Mandatory="Yes" Display="HorizontalRadios" >[CRLF] <StandardAttribute Name="Name" Attribute="DisplayName" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] <StandardAttribute Name="Location" Attribute="LocationOrName" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="No" />[CRLF] </ExclusiveChoice>[CRLF] <StandardAttribute Name="Icon" Attribute="IconPicture" Prefix="" Suffix="" Alignment="CNTR" Caption="" Mandatory="Yes" />[CRLF]</Form> 229 | PckgShowStrn=Yes 230 | Package.Comment=No 231 | Package.IconPicture=No 232 | Package_SymbolLayout= 233 | Display Model Version=Yes 234 | 235 | [DisplayPreferences\Symbol] 236 | 237 | [DisplayPreferences\Symbol\FRMEOBJ] 238 | STRNFont=新宋体,8,N 239 | STRNFont color=0, 0, 0 240 | DISPNAMEFont=新宋体,8,N 241 | DISPNAMEFont color=0, 0, 0 242 | LABLFont=新宋体,8,N 243 | LABLFont color=0, 0, 0 244 | AutoAdjustToText=Yes 245 | Keep aspect=No 246 | Keep center=No 247 | Keep size=No 248 | Width=6000 249 | Height=2000 250 | Brush color=255 255 255 251 | Fill Color=Yes 252 | Brush style=6 253 | Brush bitmap mode=12 254 | Brush gradient mode=64 255 | Brush gradient color=192 192 192 256 | Brush background image= 257 | Custom shape= 258 | Custom text mode=0 259 | Pen=1 0 255 128 128 260 | Shadow color=192 192 192 261 | Shadow=0 262 | 263 | [DisplayPreferences\Symbol\FRMELNK] 264 | CENTERFont=新宋体,8,N 265 | CENTERFont color=0, 0, 0 266 | Line style=1 267 | AutoAdjustToText=Yes 268 | Keep aspect=No 269 | Keep center=No 270 | Keep size=No 271 | Brush color=255 255 255 272 | Fill Color=Yes 273 | Brush style=1 274 | Brush bitmap mode=12 275 | Brush gradient mode=0 276 | Brush gradient color=118 118 118 277 | Brush background image= 278 | Custom shape= 279 | Custom text mode=0 280 | Pen=1 0 128 128 255 281 | Shadow color=192 192 192 282 | Shadow=0 283 | 284 | [DisplayPreferences\Symbol\FILO] 285 | OBJSTRNFont=新宋体,8,N 286 | OBJSTRNFont color=0, 0, 0 287 | DISPNAMEFont=新宋体,8,N 288 | DISPNAMEFont color=0, 0, 0 289 | LCNMFont=新宋体,8,N 290 | LCNMFont color=0, 0, 0 291 | AutoAdjustToText=Yes 292 | Keep aspect=No 293 | Keep center=No 294 | Keep size=No 295 | Width=4800 296 | Height=3600 297 | Brush color=255 255 255 298 | Fill Color=Yes 299 | Brush style=1 300 | Brush bitmap mode=12 301 | Brush gradient mode=0 302 | Brush gradient color=118 118 118 303 | Brush background image= 304 | Custom shape= 305 | Custom text mode=0 306 | Pen=1 0 0 0 255 307 | Shadow color=192 192 192 308 | Shadow=0 309 | 310 | [DisplayPreferences\Symbol\FRMPCKG] 311 | STRNFont=新宋体,8,N 312 | STRNFont color=0, 0, 0 313 | DISPNAMEFont=新宋体,8,N 314 | DISPNAMEFont color=0, 0, 0 315 | LABLFont=新宋体,8,N 316 | LABLFont color=0, 0, 0 317 | AutoAdjustToText=Yes 318 | Keep aspect=No 319 | Keep center=No 320 | Keep size=No 321 | Width=4800 322 | Height=3600 323 | Brush color=255 255 192 324 | Fill Color=Yes 325 | Brush style=6 326 | Brush bitmap mode=12 327 | Brush gradient mode=65 328 | Brush gradient color=255 255 255 329 | Brush background image= 330 | Custom shape= 331 | Custom text mode=0 332 | Pen=1 0 178 178 178 333 | Shadow color=192 192 192 334 | Shadow=0 335 | 336 | [DisplayPreferences\Symbol\USRDEPD] 337 | OBJXSTRFont=新宋体,8,N 338 | OBJXSTRFont color=0, 0, 0 339 | Line style=1 340 | AutoAdjustToText=Yes 341 | Keep aspect=No 342 | Keep center=No 343 | Keep size=No 344 | Brush color=255 255 255 345 | Fill Color=Yes 346 | Brush style=1 347 | Brush bitmap mode=12 348 | Brush gradient mode=0 349 | Brush gradient color=118 118 118 350 | Brush background image= 351 | Custom shape= 352 | Custom text mode=0 353 | Pen=2 0 128 128 255 354 | Shadow color=192 192 192 355 | Shadow=0 356 | 357 | [DisplayPreferences\Symbol\Free Symbol] 358 | Free TextFont=新宋体,8,N 359 | Free TextFont color=0, 0, 0 360 | Line style=0 361 | AutoAdjustToText=Yes 362 | Keep aspect=No 363 | Keep center=No 364 | Keep size=No 365 | Brush color=255 255 255 366 | Fill Color=Yes 367 | Brush style=1 368 | Brush bitmap mode=12 369 | Brush gradient mode=0 370 | Brush gradient color=118 118 118 371 | Brush background image= 372 | Custom shape= 373 | Custom text mode=0 374 | Pen=1 0 0 0 255 375 | Shadow color=192 192 192 376 | Shadow=0 377 | (8268, 11693) 378 | ((315,354), (433,354)) 379 | 1 380 | 15 381 | 382 | 383 | 1464181811 384 | 1464181870 385 | ((-12337,18621), (9562,-3727)) 386 | 4130 387 | 0 388 | 0 389 | 3 390 | 16777215 391 | 12632256 392 | 新宋体,8,N 393 | 394 | 395 | 1464181602 396 | 1464181680 397 | ((-3575,-6469), (-3103,-475)) 398 | ((-3273,-6469),(-3406,-475)) 399 | 0 400 | 1 401 | 0 402 | 12632256 403 | 新宋体,8,N 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 1464181608 413 | 1464181698 414 | ((-3753,-1230), (-3303,4191)) 415 | ((-3530,-1230),(-3526,1031),(-3526,4191)) 416 | 0 417 | 1 418 | 0 419 | 12632256 420 | 新宋体,8,N 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 1464181612 430 | 1464181705 431 | ((-3999,2765), (-3549,8116)) 432 | ((-3774,2765),(-3774,5617),(-3774,8116)) 433 | 0 434 | 1 435 | 0 436 | 12632256 437 | 新宋体,8,N 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 1464181616 447 | 1464181777 448 | ((-5362,6504), (-4912,12255)) 449 | ((-5138,6504),(-5137,12255)) 450 | 0 451 | 1 452 | 0 453 | 12632256 454 | 新宋体,8,N 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 1464181621 464 | 1464181784 465 | ((-5548,11202), (-5098,16509)) 466 | ((-5323,11202),(-5323,16509)) 467 | 0 468 | 1 469 | 0 470 | 12632256 471 | 新宋体,8,N 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 1464181628 481 | 1464181785 482 | ((-2821,11264), (-2371,17066)) 483 | ((-2596,17066),(-2596,11264)) 484 | 0 485 | 1 486 | 0 487 | 12632256 488 | 新宋体,8,N 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 1464181632 498 | 1464181779 499 | ((-2511,6442), (-2061,12317)) 500 | ((-2287,12317),(-2286,6442)) 501 | 0 502 | 1 503 | 0 504 | 12632256 505 | 新宋体,8,N 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 1464181634 515 | 1464181780 516 | ((1208,6690), (1658,12825)) 517 | ((1433,6690),(1433,12825)) 518 | 0 519 | 1 520 | 0 521 | 12632256 522 | 新宋体,8,N 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 1464181638 532 | 1464181782 533 | ((3997,6690), (4447,12577)) 534 | ((4221,12577),(4222,6690)) 535 | 0 536 | 1 537 | 0 538 | 12632256 539 | 新宋体,8,N 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 1464181640 549 | 1464181703 550 | ((3195,-1230), (3648,8054)) 551 | ((3416,8054),(3416,2828),(3426,-1230)) 552 | 0 553 | 1 554 | 0 555 | 12632256 556 | 新宋体,8,N 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 1464181642 566 | 1464181701 567 | ((3306,-5788), (3775,-98)) 568 | ((3488,-98),(3593,-5788)) 569 | 0 570 | 1 571 | 0 572 | 12632256 573 | 新宋体,8,N 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 浏览器 583 | 1464181328 584 | 1464181660 585 | ((-7945,-5599), (6005,-9799)) 586 | 4130 587 | 0 588 | 0 589 | 16777215 590 | 12632256 591 | 新宋体,8,N 592 | 1 593 | 594 | 595 | 路由(route) 596 | 1464181450 597 | 1464181720 598 | ((-8100,2172), (300,4722)) 599 | 4130 600 | 0 601 | 0 602 | 16777215 603 | 12632256 604 | 新宋体,8,N 605 | 606 | 607 | 请求处理器(request handler) 608 | 1464181457 609 | 1464181758 610 | ((-8100,6149), (5700,8699)) 611 | 4130 612 | 0 613 | 0 614 | 16777215 615 | 12632256 616 | 新宋体,8,N 617 | 1 618 | 619 | 620 | orm 621 | 1464181461 622 | 1464181764 623 | ((-8024,10724), (-1350,12974)) 624 | 4130 625 | 0 626 | 0 627 | 16777215 628 | 12632256 629 | 新宋体,8,N 630 | 631 | 632 | 模板引擎 633 | 1464181463 634 | 1464181769 635 | ((-374,10725), (5700,13049)) 636 | 4130 637 | 0 638 | 0 639 | 16777215 640 | 12632256 641 | 新宋体,8,N 642 | 1 643 | 644 | 645 | 数据库 646 | 1464181468 647 | 1464181775 648 | ((-8250,15299), (5550,17549)) 649 | 4130 650 | 0 651 | 0 652 | 16777215 653 | 12632256 654 | 新宋体,8,N 655 | 656 | 657 | 服务器软件 658 | 1464181548 659 | 1464181749 660 | ((-8064,-1784), (6034,540)) 661 | 4130 662 | 0 663 | 0 664 | 16777215 665 | 12632256 666 | 新宋体,8,N 667 | 668 | 669 | 服务器 670 | 1464181878 671 | 1464181906 672 | ((-12019,16559), (-9400,18358)) 673 | 4130 674 | 0 675 | 16777215 676 | 16777215 677 | 12632256 678 | 新宋体,8,N 679 | 1 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | --------------------------------------------------------------------------------