Code Monkey home page Code Monkey logo

smartonmyoji's Issues

封号

大佬我被封了呢,您有被封过吗

能说下原理吗?

你好, 对原理感兴趣.
看到你截图的代码部分,模拟器是调用win32api, 手机是adb Screencap. 然后匹配的时候用<模板> 和 <特征点> 匹配, 有个问题. 那如果我的手机或模拟器分辨率和你截图时的分辨率不同. 程序怎么保证在我设备上正常运行呢?

一个问题

前置:
用于挖土,使用桌面客户端,单刷。

描述
使用了几天,发现一个问题,就是 在挖土结算页面,会偶尔点到 概率up ,使页面弹出 概率up 介绍信息,页面整体变暗,特征图像被遮挡,程序无法进行下一步,建议加入相关特征图像以排查该情况。

相关设置:
点击坐标偏移:43 像素

建议补全该特征以解决此问题。

还有就是暂停两分钟时,希望出一个提示音的选项,让用户这段时间内手动操作或者进行其他操作以混淆行为。

win7截图失败

win7系统下

  1. 正常模式 : 截图不全,右边重点按钮区域都没有

2.兼容模式报错:

初始化中…
第 [ 1 ] 次匹配, 当前进度 [ 0.31% ]
开始-结束时间 [ 12-04 01:13 --- 12-04 02:13 ]
正在截图…
未知原因导致异常中断,10秒后重试……

鼠标点击 多窗口和模拟器问题

您好,我想请问下,如果多个游戏窗口的话,鼠标点击事件可以并发操作吗? 另外这个切图和坐标工具这一套是什么实现的

谢谢了。一些问题麻烦指导。

问题请教

作者您好,我以前学过python,当然我也很喜欢玩阴阳师,我用pyautogui对于mumu模拟器以外的空间进行操作时可以,但是在作用于模拟器时却无效了是怎么回事?就是可以指示鼠标自动移动至模拟器窗口内,但是却不可以自动点击或者说没有反应。求解实在是想不明白

图片点击定位问题

请问一下,这个图片点击是以图片正中心为中点,点击坐标便宜为半径的分布吗?
以探索为例,人手动操作的时候,每次打完小怪后的点击范围其实很大,基本半个屏幕都可能点到。只是重复点击宝箱图案内,其实有点违背平时点击习惯,这是否会被纳入检测范围?
我有一个想法,可以根据图库里的图片大小,让图片里的位置都可以随机点到。这样使用者只需要调整图库里的图片,点击是截图内的位置随机选取。不知道这个想法是不是已经纳入了代码,还是说有更合理的处理方式。

使用mumu模拟器需不需要修改图片库?

我自己试了一下好像是不能够识别的,我自己也修改过图片库(结束的那个达摩瓶子始终识别不上),发现它识别了图片但是没有点击效果,有点奇怪。请问大佬,mumu是能正常用吗?

关于随机点击模型 ~

random.randint 平均分布

random randint pos
random_randint(5000)

random.normal 正态分布

random normal pos
random_nomal(5000)

random.normal 正态分布模型处理

标准正态分布和处理后的对比

取样模拟(100、500、1000、2000、5000)

100
500
1000
2000
5000

模拟3个不同点,500次点击

500次

功能建议

可不可以加一个自动选取几号位式神的功能,

违规了

最新版本,刷了两个40分钟,中间停个半个多小时
F631CB4A-6D0D-4C99-ABC1-403A7D25473D

是否考虑增加自动检测配置文件

  1. 举个例子,把原来的 config.ini 文件改名为 config.example.ini,然后在程序启动时检测是否存在 config.ini,如果不存在,则将默认配置复制一份进行重命名,如果存在,则跳过。这样在更新的时候就不会覆盖掉原先已经改好的设置
  2. 另外就是可否在右上角添加一个按钮,让程序图标能够缩小到右下角托盘里面

双开遇到的问题

首先感谢作者的脚本!当我使用yuhun文件进行桌面版双开刷魂土时,会遇到当其中一个窗口进入组队界面等待,另一个窗口还在胜利结算界面,此时进行防异常时间等待,因此等待过后错过时间无法组队。经过实践测试,这种情况出现的概率还是比较高的,请问是我的设置没有调整好吗?我可以如何调整解决呢?

需求:匹配到某个模板图片后,脚本停止运行 ,并提示完成

背景:游戏中体力刷完,或者某个活动达到上限,会有提示,脚本也应当作出相应的反应,不要一直运行
方案:通过对模板图片名称识别、判断以实现功能(模板图片的名称已有记录)

……
config中增加配置项,配置需要停止的情况(体力不够、活动次数上限)
if_match_then_stop : true
target_img_name : end.jpg, xx1.jpg, xx2.jpg, xx3.jpg
……
匹配方法(ModuleStartMatching.py)
target_img_name = target_info[2]
……
stop_status == false
pos, target_num = get_pos.get_pos_by_xxxx(……)
通过num找到img文件名(循环查找多个匹配名)
if target_img_name == config[i]
    stop_status == true
    return stop_status
……
线程终止(ModuleRunThread.py)
if stop_status :
    播放提示音
    self.mutex.unlock()
    self.finished_signal.emit(True)
    break

雷电模拟器只能使用兼容模式

正在截图…
截图成功!
正在匹配…
匹配成功!
匹配到第 [ 3 ] 张图片: [ 1 ]
坐标位置: [ 1002 , 548 ]
点击坐标: [ 1021 , 526 ]
正常模式下他的点击似乎没有反应(无遮挡且调试模式看窗口正常)
另外问一下双开组队刷御魂要怎样设置

雷电模拟器

运行异常, 小白不知道怎么解决 大大帮帮忙
无标题

目前遇到的bug

结界突破一直点刷新,百鬼无反应,魂土伤害结算界面不点击,自己手动替换阿修罗图片才解决,个人觉得可以模块化这些图片,开始,准备,结算,奖励这几个按钮由用户自行截图设置,也方便不用做太多分辨率的调整

后台点击不支持安卓模拟器

没下到阴阳师的PC版,现在只有模拟器版。然后后台点击在模拟器环境下(MuMu模拟器)是没有反应的。
测试了其他程序(Chrome)是可以后台点击的。

待优化内容 ~

  • 模拟真实点击的算法,需要根据截图的范围大小确定点击的随机位置(另外增加限制,每X次点击触发N次) 改为从正态分布的数组中抽取,而不是平均分布中取样
  • 随机等待的触发机制优化,(增加限制,每X次匹配成功最多触发Y次等待)
  • 代码简化,每次匹配前的初始化部分代码,有点过于混乱(当时为了考虑各种情况,部分代码可以封装为函数调用)
  • 对模拟器多开兼容(先找找能不能获取到端口号,找不到就只有配置文件手动加了)
  • 优化脚本的等待时间,限制10分钟不超过N次点击,每次匹配间隔设置上下限时间
  • 匹配速度优化,去除部分没有必要的延迟,尝试对截图预处理看看能否提升匹配速度(分辨率过大的提前压缩,转灰度/二值化处理)
  • 安卓端移植,参考 https://www.zhihu.com/column/c_1500045392640786432https://github.com/superzhangjh/AutoTouch

关于正常模式截图问题

作者您好
开正常模式进行调试会发现,截图是黑屏,或者只有坐上一部分,尝试修改缩放比例未果,请问这是为什么呢。开兼容模式可以正常截图。

Error Information:

Error Information:
Type:
Value:OpenCV(4.5.4) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'
Traceback:

考虑支持3人队伍吗?

开了3个号组队魂土,但是识图到就会点击,队伍两个人就会开始打;期望有个开关的配置可以判断一下组满再开始

特征点匹配模式问题

在探索里面使用特征点匹配无法匹配到打完boss结算的那个小宝箱,重新截图试了几次都不行
reward

关于双开的问题

请问双开的时候,截屏、点击顺序是什么?
我发现,打开多开以后,有时候司机点的慢,有时候又快。
司机和打手很大概率不会同时截屏点击。
请问是有什么设置吗?还是说是我电脑配置不够的问题?

运行速度

程序运行一段时间后速度变得很慢,匹配时间呈现线性增长

  • window桌面版单窗体,正常模式模板匹配
  • 一样的环境下

RN$T%F2GP)RGESP$WO_EE U

{4B73L8B F5BNLZ7{D8$2

2F)9)I OU7K0@TMZT2C~X

关于模拟器前台的一些个人经验

经测试在雷电模拟器下是可以的,只需要添加一行代码,可以移步最后面。

可以用spy++查看,模拟器最顶端是一个模拟器的窗口,然后还有subwindow,

例如雷电模拟器,

窗口名字:
雷电模拟器
TheRender
sub

获取到这个TheRender的handle给handle_num即可

另外,木木模拟器实测无法完成点击,有可能是对后台模拟操作进行了屏蔽。

自用偷懒的改法,

diff --git a/modules/ModuleHandleSet.py b/modules/ModuleHandleSet.py
index 73f1856..4c00ba9 100644
--- a/modules/ModuleHandleSet.py
+++ b/modules/ModuleHandleSet.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+import win32gui
 from os.path import abspath, dirname
 from win32api import OpenProcess
 from win32con import PROCESS_ALL_ACCESS
@@ -20,6 +21,8 @@ class HandleSet:
     def get_handle_num(self):
         """通过句柄标题获取句柄编号"""
         self.handle_num = FindWindow(None, self.handle_title)  # 搜索句柄标题,获取句柄编号
+        self.handle_num = win32gui.FindWindowEx(self.handle_num, 0, None, "TheRender")
+        print("adjust handle to", self.handle_num)
         if self.handle_num == 0:
             print("目标程序未启动,即将中止!")
             return None  # 返回异常

🧙‍♂️关于脚本采用的防检测算法说明

脚本辅助不会像外挂辅助一样会修改游戏内的数据,只能通过特定的找图、找色,然后执行对应的交互动作(硬件模拟交互和软件模拟交互,游戏基本分辨不出和鼠标点击的区别),脚本可以做的很简单,也可以扩展的非常复杂,相对来说,比起修改内存的外挂辅助更加容易编写。所以这一类型的脚本辅助的防检测方法,不需要考虑如何骗过游戏服务器,仅需要针对“用户行为特征”进行算法上的优化就能很好的做到防检测、防封。
注:此方法也不能保证完全避免被封号,也有可能因为被举报导致被封,若被封号可自行分析日志判断原因,也可尝试申述~


游戏平台如何通过用户行为判断异常

“用户行为特征检测”,即游戏后台基于用户数据,识别用户行为是否异常。以下内容,基于“如果我是策划,我会如何检测用户的异常行为”来思考的流程,可能还有未考虑到的部分,欢迎大家提出思路。

1、记录用户以下行为数据,并上传服务器:

  • 登录时间、下线时间
  • 发生交互的类型:点击、拖拽、长按、移动鼠标(存疑,基本不可能)
  • 发生交互的时间:时间戳格式,可以精确到毫秒
  • 发生交互的坐标:x,y,也可能是一个百分比
  • 发生交互的功能:页面ID、按钮ID
  • 如:2022-10-22 13:32:44:19 click "Button_19932" [993,337]

2、通过以上行为数据,可以进行以下统计:

  • 每隔固定时间段内进行交互的次数,比如每1小时的点击次数
  • 每隔固定时间段内的点击热力图、比如每1小时的点击热力图

3、通过上述统计,可以做出以下异常行为判断,每个异常行为给到一定权重

  • 某服活跃玩家在 早9-晚12 点,如果玩家不在这个时间内发生了交互行为,则标记为异常(1分)
  • 某个时间内,玩家点击频率非常固定,比如9-12点,每10分钟都发生了40次点击,则标记异常(2分)
  • 某个时间内,玩家点击目标非常固定,比如9-12点,仅点击了 开始按钮、结算奖励界面,未进行其他交互,则标记异常(1分)
  • 某个时间内,玩家点击坐标非常固定,比如9-12点,发生了1000次点击,其中有200次点了[881,983],有100次点了[220,183],则标记异常(5分)
  • 某个时间内,玩家点击坐标范围非常固定,比如9-12点,发生了1000次点击,有500次均点了[881,983] - [220,183]这个范围,另外500次均点了[132,183] - [720,583]这个范围,则标记异常(2分)
  • 某个时间内,玩家点击坐标范围形状规律,比如2022-10-22日,点击热力图呈现为几个的圆形或矩形,则标记为异常(3分)
  • 有封号历史的,默认重点监控(1分)
  • 被多人共同举报的,转人工审查(2分)
  • 注:如果检测机制使用的是机器学习,把正常玩家日志数据通过学习生成模型,用于整体的用户行为识别,那么AI也是采用类似权重标记的方式,找出哪些属于异常的数据;

4、通过权重计分,二次审核或直接封号

  • 比如满5分,则推送给运营人员,由运营人员进行人工审核,其中满10分的,直接封号
  • 封号后保留异常数据(用户申诉后便于核实),并标记该账号


本脚本采用哪些方法规避行为异常

随机延迟 - 人类交互行为不会总那么稳定

  • 人类行为不会那么稳定,所以为每次匹配,进行随机延迟
  • 点击时也不会非常稳定,所以为每次点击,随机延迟(0.1s-0.2s)
  • 人类在玩游戏会被其他事情打扰,所以随机时间内,随机等待(10s-60s)

随机偏移 - 人类交互行为不会总那么精准,但有规律可循

  • 针对获得的坐标,进行一次指定范围内的偏移
  • 针对偏移坐标,设计正态分布算法模型,使点击范围符合正态分布规律
  • 针对正态分布点击模型,进行二次处理(缩放、长尾),使点击的分布不是均匀的正态分布
  • 针对部分结算界面,针对匹配目标进行较大范围偏移,模拟人的行为(人类不会只盯着文字或者关键图片点)

额外点击 - 人不会像程序那么死板

  • 在点击时点不动,会习惯多点几次
  • 不会只点击一个位置,理论上全屏幕都会点击


实现效果

使用点击模型与未使用正态分布模型的对比(未使用匹配图片json偏移)

可以看出,一般的随机偏移,会呈现规律的形状
image

经过二次处理的正态分布点击模型与原始的模型对比

很明显,未处理前,坐标分布非常均匀
image

仅关键匹配图片json配置1000次魂土(未针对偏移使用大模型)

感觉对了,但是点的也比较集中,看起来不够自然
image

当前最新算法结果(v0.39) - 关键匹配图片json配置 + 结合合大偏移模型

点的范围更加分散,但是也呈现一定的非均匀正态分布的规律

魂土(40min左右)
image

化四季活动副本(400次点击)
image

手动点击效果 - 痴 350次点击

相对于脚本,手动点击的坐标分布更加集中一点,也是呈现正态分布+大范围偏移点击效果
image

最新版脚本点击效果(v0.40+)

对偏移坐标缩放扁平化,更加接近真实的点击
image


模拟工具

生成脚本点击日志:模拟脚本的点击算法,指定位置点击N次,坐标规律与脚本实际点击一致
https://github.com/aicezam/SmartOnmyoji/blob/main/modules/tools/simulation_real_click.py
获取手动点击日志:仅支持桌面版,调整代码可以支持其他程序
https://github.com/aicezam/SmartOnmyoji/blob/main/modules/tools/get_mouse_click_pos.py
日志分析工具:仅支持固定格式
https://github.com/aicezam/SmartOnmyoji/blob/main/modules/tools/log_analysis.html


补充资料

关于手游的外挂、反作弊的专利(网易-2022年):
一种游戏中的外挂检测方法、装置、电子设备及存储介质(CN114832384A)
一种游戏外挂检测方法、装置、电子设备及可读存储介质(CN114712861A)
image
外挂检测流程

大佬求解决awa

[ WARN:[email protected]] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\img\yuhun\end_fail.jpg'): can't open/read file: check file path/integrity
Traceback (most recent call last):
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 73, in
main()
File "C:\Users\DJS\AppData\Local\Programs\Python\Python39\lib\site-packages\gooey\python_bindings\gooey_decorator.py", line 134, in
return lambda *args, **kwargs: func(*args, **kwargs)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 54, in main
start_click(args.connect_mod, args.modname, args.hwd_title, args.click_deviation, args.interval_seconds,
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleStart.py", line 65, in start_click
target_info = GetTargetPicInfo(modname, compress_val=1).get_target_info # 目标图片不压缩(本身就小)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleGetTargetInfo.py", line 80, in get_target_info
img_hw[i] = img.shape[:2] # 获取目标图片宽高
AttributeError: 'NoneType' object has no attribute 'shape'
目标图片读取中……
[ WARN:[email protected]] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\img\huodong\end_fail.jpg'): can't open/read file: check file path/integrity
Traceback (most recent call last):
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 73, in
main()
File "C:\Users\DJS\AppData\Local\Programs\Python\Python39\lib\site-packages\gooey\python_bindings\gooey_decorator.py", line 134, in
return lambda *args, **kwargs: func(*args, **kwargs)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 54, in main
start_click(args.connect_mod, args.modname, args.hwd_title, args.click_deviation, args.interval_seconds,
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleStart.py", line 65, in start_click
target_info = GetTargetPicInfo(modname, compress_val=1).get_target_info # 目标图片不压缩(本身就小)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleGetTargetInfo.py", line 80, in get_target_info
img_hw[i] = img.shape[:2] # 获取目标图片宽高
AttributeError: 'NoneType' object has no attribute 'shape'
目标图片读取中……
[ WARN:[email protected]] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\img\huodong\end_fail.jpg'): can't open/read file: check file path/integrity
Traceback (most recent call last):
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 73, in
main()
File "C:\Users\DJS\AppData\Local\Programs\Python\Python39\lib\site-packages\gooey\python_bindings\gooey_decorator.py", line 134, in
return lambda *args, **kwargs: func(*args, **kwargs)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 54, in main
start_click(args.connect_mod, args.modname, args.hwd_title, args.click_deviation, args.interval_seconds,
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleStart.py", line 65, in start_click
target_info = GetTargetPicInfo(modname, compress_val=1).get_target_info # 目标图片不压缩(本身就小)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleGetTargetInfo.py", line 80, in get_target_info
img_hw[i] = img.shape[:2] # 获取目标图片宽高
AttributeError: 'NoneType' object has no attribute 'shape'
目标图片读取中……
[ WARN:[email protected]] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\img\huodong\end_fail.jpg'): can't open/read file: check file path/integrity
Traceback (most recent call last):
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 73, in
main()
File "C:\Users\DJS\AppData\Local\Programs\Python\Python39\lib\site-packages\gooey\python_bindings\gooey_decorator.py", line 134, in
return lambda *args, **kwargs: func(*args, **kwargs)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 54, in main
start_click(args.connect_mod, args.modname, args.hwd_title, args.click_deviation, args.interval_seconds,
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleStart.py", line 65, in start_click
target_info = GetTargetPicInfo(modname, compress_val=1).get_target_info # 目标图片不压缩(本身就小)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleGetTargetInfo.py", line 80, in get_target_info
img_hw[i] = img.shape[:2] # 获取目标图片宽高
AttributeError: 'NoneType' object has no attribute 'shape'
目标图片读取中……
[ WARN:[email protected]] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\img\yuhun\end_fail.jpg'): can't open/read file: check file path/integrity
Traceback (most recent call last):
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 73, in
main()
File "C:\Users\DJS\AppData\Local\Programs\Python\Python39\lib\site-packages\gooey\python_bindings\gooey_decorator.py", line 134, in
return lambda *args, **kwargs: func(*args, **kwargs)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\smart_onmyoji_start.py", line 54, in main
start_click(args.connect_mod, args.modname, args.hwd_title, args.click_deviation, args.interval_seconds,
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleStart.py", line 65, in start_click
target_info = GetTargetPicInfo(modname, compress_val=1).get_target_info # 目标图片不压缩(本身就小)
File "C:\Users\DJS\OneDrive\桌面\GG\yys\python\SmartOnmyoji-main\modules\ModuleGetTargetInfo.py", line 80, in get_target_info
img_hw[i] = img.shape[:2] # 获取目标图片宽高
AttributeError: 'NoneType' object has no attribute 'shape'

探索副本

探索是只能等怪走过来才能匹配到吗?还是得自己手动点击移动

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.