记录一次曲折的需求完成

2023-10-31 18:20

本文主要是介绍记录一次曲折的需求完成,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

需求:

将WPF程序中一段调用Cgal编译的dll的treemap算法 改成 调用d3.js中的packing Circle算法

重要程度

⭐⭐⭐⭐

人物性格:

非常懒

时限

10小时

思路

一.将d3.js打包成dll,然后WPF调用(因为C#中有现成的调用dll代码,因此修改的非常少)

a) 尝试JScript.NET

在VS开发人员命令行中输入

 jsc /t:library d3.js

报错

D://1.js(2,323) : error JS1160: 特性列表不适用于当前上下文
D://1.js(2,334) : error JS1193: 应为“,”或“)”
D://1.js(2,449) : error JS1018: “return”语句在函数范围外
D://1.js(2,479) : error JS1195: 应为表达式
D://1.js(2,513) : error JS1195: 应为表达式
D://1.js(2,527) : error JS1004: 应为“;”
D://1.js(2,543) : error JS1004: 应为“;”
D://1.js(2,552) : error JS1010: 应为标识符
D://1.js(2,661) : error JS1195: 应为表达式
D://1.js(2,676) : error JS1010: 应为标识符
D://1.js(2,677) : warning JS1111: 已经定义了“t”
D://1.js(2,780) : error JS1002: 语法错误
D://1.js(2,825) : error JS1111: 已经定义了“i”
D://1.js(2,881) : error JS1160: 特性列表不适用于当前上下文
D://1.js(2,911) : error JS1004: 应为“;”
D://1.js(2,913) : error JS1004: 应为“;”
D://1.js(2,916) : error JS1006: 应为“)”
D://1.js(2,917) : error JS1004: 应为“;”
D://1.js(2,947) : error JS1160: 特性列表不适用于当前上下文
D://1.js(2,964) : error JS1004: 应为“;”
D://1.js(2,966) : error JS1004: 应为“;”
D://1.js(2,969) : error JS1006: 应为“)”
D://1.js(2,970) : error JS1004: 应为“;”
D://1.js(2,978) : error JS1197: 错误太多。该文件可能不是 JScript 文件

放弃

二.WPF直接调用js代码

a) 尝试MSScriptControl.ScriptControl

//string _MD5_js = "MD5.js";private object ExecuteScript(string funcName, string argument, string jsPath){string js = System.IO.File.ReadAllText(jsPath);object o = ExecuteScript(string.Format("{0}('{1}')", funcName, argument), js);return o;}/// <summary>/// 执行JS/// </summary>/// <param name="sExpression">参数体</param>/// <param name="sCode">JavaScript代码的字符串</param>/// <returns></returns>private object ExecuteScript(string sExpression, string sCode){MSScriptControl.ScriptControl scriptControl = new MSScriptControl.ScriptControl();scriptControl.UseSafeSubset = true;scriptControl.Language = "JScript";scriptControl.AddCode(sCode);try{return scriptControl.Eval(sExpression);}catch (Exception ex){}return null;}

报错
在这里插入图片描述
放弃

三.Asp.net后台调用js代码,然后WPF通过post获取数据(因为Asp.net有现成的post函数)

a) 尝试ValuesController.cs中在Post函数中调用JS代码

在这里插入图片描述
对MVC不是特别熟,没有余力去思考ValuesController对应的view在哪儿了
放弃

四.直接写一个post服务器,然后WPF通过post获取数据

服务器

// postserver.js
// 获取客户端post来的title、text参数,然后返回给客户端var http = require('http');
var querystring = require('querystring');var server = http.createServer(function(req, res) {var post = '';req.on('data', function(chunk) {post += chunk;});req.on('end', function() {post = querystring.parse(post);res.write(post.title);res.write(post.text);res.end();});
}).listen(3000);

在控制台中执行node server.js,开启http服务,监听3000端口。

客户端

var http = require('http');
var querystring = require('querystring');var contents = querystring.stringify({title: 'Hello ',text: 'Arthur',
});var options = {host: '127.0.0.1',port: '3000',  //非80端口需要指定,如果是80端口则可以省略。path: '/',headers: {'Content-Type': 'application/x-www-form-urlencoded','Content-Length': contents.length}
};var req = http.request(options, function(res) {res.setEncoding('utf8');res.on('data', function(data) {console.log('request begin:');console.log(data);console.log('request end.');console.log('--------------------');});
});req.write(contents);
req.end();

在另一个控制台中执行node client.js

a) 安装Nodejs

b) 写一个简单的post服务器和客户端测试

在这里插入图片描述
成功

c) 在post服务器中调用d3.js

var d3 = require("./d3.js");

报错

ReferenceError: XMLHttpRequest is not definedat nu (C:\Users\lunhui\Desktop\d3.js:2:63462)at Object.json (C:\Users\lunhui\Desktop\d3.js:2:65084)at d33 (C:\Users\lunhui\Desktop\test.js:41:8)at IncomingMessage.<anonymous> (C:\Users\lunhui\Desktop\test.js:21:18)
[90m    at IncomingMessage.emit (node:events:406:35)[39m
[90m    at endReadableNT (node:internal/streams/readable:1329:12)[39m
[90m    at processTicksAndRejections (node:internal/process/task_queues:83:21)[39m
α)尝试1:

原因:xmlhttprequest 不是Node 内置的,需要单独安装:
安装命令:npm install xmlhttprequest

失败

β)尝试2:

搜索nodejs调用d3.js
报错
在这里插入图片描述
安装express

npm install express

然后不报错了,但是脚本也没用
失败

γ)尝试3:

找到一份代码node.js中用d3.js

npm install d3

报错
在这里插入图片描述
尝试解决方案1
Check for 2 things:

Node version >= 14. It only works with latest version of node.
Make sure your package.json includes a line for “type”: “module”, Without this line node assumes you want to use Common JS modules rather than ESM.

报错
在这里插入图片描述
尝试解决方案2
在你要require的代码前引入如下代码即可:

import { createRequire } from 'module';
const require = createRequire(import.meta.url);

报错
在这里插入图片描述
尝试解决方案3
在 Node.js 中使用 import
Node 版本需在 9.0 及以上
不加 loader 时候,使用 import/export 的文件后缀名必须为 .mjs

import d3 from 'd3'

在这里插入图片描述
修改为

import * as d3 from 'd3';

其他的require也都要改成这个亚子
成功!

d) 尝试连接
报错

ReferenceError: fetch is not defined

在node_module/d3_fectch/src/json.js开头添加以下两句

import { fetch as fetchPolyfill } from 'whatwg-fetch'
global.fetch = fetchPolyfill

报错
在这里插入图片描述
把var转换成字符串

报错
在这里插入图片描述
node_modules\whatwg-fetch\dist\fetch.umd.js
添加

 import * as XMLHttpRequest from 'xmlhttprequest';

报错
在这里插入图片描述
这是个终极大错!
退无可退!
放弃不了了!
现在已经22点.明天记续

给明天留个希望: d3.json()和d3.csv()出了问题,也就是读取文件出了问题

五.中期总结

我好像没有时间详细记录问题和解决方案了,只能草草描述.

果然是读取文件出了问题
换成了fs.readFileSync就再也没有报错了
然而接下来的第二天时间却浪费在了d3.js的返回数据格式上

这件事给我的教训是 一定要先去看说明文档,不要自己想当然的测试
https://observablehq.com/@d3/d3-hierarchy1

第三天的时间浪费在了fs.readFileSync之后没有转化成Json格式.

var root = JSON.parse(fs.readFileSync('./flare-2.json', 'utf8'));

成功输出正确格式的root;
终于,马上要成功了.

然而好像并没有那个简单,除了根节点的x,y被计算出来,其他的所有属性都没有记录.

六.神奇的转折-C#

结果在github找到一个C#的circle packing程序
Circle Packing Algorithm for C# (in a Windows Universal project)
兜兜转转又回到最初的起点

正在下载相关组件,测试是否work
发现Visual Studio 2017 和Visual Studio 2019 都打不开UWP项目
期间测试了一波下载Visual Studio 2015
失败

Visual Studio 2019 加载UWP项目
失败

于是直接从源代码里摘出来放到WPF项目中,然而,发现并不是自己需要的效果
失败
在这里插入图片描述

七.重回Html

又回到Github,找到了Html
Github:balakrishna-k/CirclePack
这个能运行
在这里插入图片描述
并且可以获取到数据的返回值,很是成功.

var circle = g.selectAll("circle").data(nodes).enter().append("circle").attr("class", function(d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; });alert(circle._groups[0][0].__data__.x);

八.Html的Socket通信

html的websocket与我已有的C#的TCP socket连接失败
Websocket错误:ERR_INVALID_HTTP_RESPONSE
原因是:
在这里插入图片描述
因此实现了一个C#的WebSocket的服务器,连接成功.

最终我的伞兵架构为下图:
在这里插入图片描述
1.把服务端放在服务器而不是本地上是因为快速解决跨域问题(后来放弃了,因为外网IP的问题,最后放在了本地IIS服务器上)
2.写两个socket是因为WPF和服务端的Tcp socket是现成的,最简单的修改是直接websocket与tcp socket之间互传字符串

九.最终调试

在这里插入图片描述
经过了几个小bug,最终三个程序联调成功.(C#服务器调用UI组件一定要用Dispatcher.BeginInvoke,否则会出各种奇怪的bug)

剩下的就是规范数据传输格式,封装函数等工作了.

十.总结

看似初衷是为了省事,实则花费了更多时间和精力.
究竟是变通了,不撞南墙了?还是浮躁了,静不下来了呢?

十一.番外

如同之前很多次一样,在一切都结束的时候,我才突然意识到,d3.js中的packing Circle算法不能计算非矩形内的packing circle.
因此,这些工作好像都没有用上.
之前是想得太多,做的太少.现在是想的太少,直接去莽.
都是教训

这篇关于记录一次曲折的需求完成的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/317241

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

python安装完成后可以进行的后续步骤和注意事项小结

《python安装完成后可以进行的后续步骤和注意事项小结》本文详细介绍了安装Python3后的后续步骤,包括验证安装、配置环境、安装包、创建和运行脚本,以及使用虚拟环境,还强调了注意事项,如系统更新、... 目录验证安装配置环境(可选)安装python包创建和运行Python脚本虚拟环境(可选)注意事项安装

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

电脑多久清理一次灰尘合? 合理清理电脑上灰尘的科普文

《电脑多久清理一次灰尘合?合理清理电脑上灰尘的科普文》聊起电脑清理灰尘这个话题,我可有不少话要说,你知道吗,电脑就像个勤劳的工人,每天不停地为我们服务,但时间一长,它也会“出汗”——也就是积累灰尘,... 灰尘的堆积几乎是所有电脑用户面临的问题。无论你的房间有多干净,或者你的电脑是否安装了灰尘过滤器,灰尘都

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓