Compare commits

...

12 Commits

Author SHA1 Message Date
MistEO
028f1ff182 Merge branch 'master' of https://github.com/MistEO/MeoAssistance 2021-07-17 01:06:59 +08:00
MistEO
41a3695556 fixed a filename typo 2021-07-17 01:06:50 +08:00
MistEO
9521285376 Update README.md 2021-07-17 00:47:39 +08:00
MistEO
48125e241b update readme 2021-07-17 00:43:31 +08:00
MistEO
91dad862f8 update gui and readme 2021-07-17 00:35:55 +08:00
MistEO
ff01ce3af4 update configer interface and GUI 2021-07-17 00:03:21 +08:00
MistEO
b701a7ad99 udpate configer 2021-07-16 23:01:40 +08:00
MistEO
96200d5ca6 update gui project 2021-07-16 21:09:57 +08:00
MistEO
0a89b1b48a merge remote 2021-07-16 20:49:26 +08:00
MistEO
11fa36aaaf support Visit Ins 2021-07-16 20:45:02 +08:00
MistEO
78ad680067 update task max_times 2021-07-16 17:51:59 +08:00
MistEO
30cea829f3 add GUI 2021-07-16 07:16:48 +08:00
37 changed files with 1502 additions and 168 deletions

389
.gitignore vendored
View File

@@ -36,3 +36,392 @@ Release
.vs
*.vcxproj.user
*.swp
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Nuget personal access tokens and Credentials
nuget.config
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
.idea/
*.sln.iml

View File

@@ -16,38 +16,64 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sanity", "Tools\Sanity\Sani
{9CC7838E-D5FB-4771-848D-5F83D638C5AD} = {9CC7838E-D5FB-4771-848D-5F83D638C5AD}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeoAsstGui", "MeoAsstGui\MeoAsstGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
{9CC7838E-D5FB-4771-848D-5F83D638C5AD} = {9CC7838E-D5FB-4771-848D-5F83D638C5AD}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|Any CPU.ActiveCfg = Debug|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.ActiveCfg = Debug|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x64.Build.0 = Debug|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x86.ActiveCfg = Debug|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Debug|x86.Build.0 = Debug|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|Any CPU.ActiveCfg = Release|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.ActiveCfg = Release|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.Build.0 = Release|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x64.ActiveCfg = Debug|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x64.Build.0 = Debug|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x86.ActiveCfg = Debug|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Debug|x86.Build.0 = Debug|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|Any CPU.ActiveCfg = Release|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x64.ActiveCfg = Release|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x64.Build.0 = Release|x64
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x86.ActiveCfg = Release|Win32
{9CC7838E-D5FB-4771-848D-5F83D638C5AD}.Release|x86.Build.0 = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|Any CPU.ActiveCfg = Debug|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x64.ActiveCfg = Debug|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x64.Build.0 = Debug|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x86.ActiveCfg = Debug|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Debug|x86.Build.0 = Debug|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|Any CPU.ActiveCfg = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.ActiveCfg = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.Build.0 = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x86.ActiveCfg = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x86.Build.0 = Release|Win32
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.ActiveCfg = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x64.Build.0 = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x86.ActiveCfg = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Debug|x86.Build.0 = Debug|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|Any CPU.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -19,14 +19,16 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\AsstDef.h" />
<ClInclude Include="include\Assistance.h" />
<ClInclude Include="include\AsstCaller.h" />
<ClInclude Include="include\AsstDef.h" />
<ClInclude Include="include\Configer.h" />
<ClInclude Include="include\Identify.h" />
<ClInclude Include="include\WinMacro.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Assistance.cpp" />
<ClCompile Include="src\AsstCaller.cpp" />
<ClCompile Include="src\Configer.cpp" />
<ClCompile Include="src\Identify.cpp" />
<ClCompile Include="src\WinMacro.cpp" />

View File

@@ -15,9 +15,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Assistance.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Configer.h">
<Filter>头文件</Filter>
</ClInclude>
@@ -30,11 +27,14 @@
<ClInclude Include="include\AsstDef.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Assistance.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\AsstCaller.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Assistance.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Configer.cpp">
<Filter>源文件</Filter>
</ClCompile>
@@ -44,6 +44,12 @@
<ClCompile Include="src\WinMacro.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Assistance.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\AsstCaller.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\resource\config.json">

View File

@@ -5,6 +5,7 @@
#include <condition_variable>
#include <memory>
#include <optional>
#include <unordered_map>
#include "AsstDef.h"
@@ -19,24 +20,27 @@ namespace asst {
~Assistance();
std::optional<std::string> setSimulator(const std::string & simulator_name = std::string());
void start();
// void pause();
void start(const std::string & task);
void stop();
bool setParam(const std::string& type, const std::string& param, const std::string& value);
private:
static void working_proc(Assistance* pThis);
static void workingProc(Assistance* pThis);
std::shared_ptr<WinMacro> m_pWindow = nullptr;
std::shared_ptr<WinMacro> m_pView = nullptr;
std::shared_ptr<WinMacro> m_pCtrl = nullptr;
std::shared_ptr<Identify> m_Ider = nullptr;
std::shared_ptr<Identify> m_pIder = nullptr;
bool m_inited = false;
std::thread m_working_thread;
std::mutex m_mutex;
std::condition_variable m_condvar;
bool m_thread_exit = false;
bool m_thread_running = false;
json::array m_next_tasks;
std::vector<std::string> m_next_tasks;
};
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "Assistance.h"
#ifdef __cplusplus
extern "C" {
#endif
extern __declspec(dllexport) asst::Assistance* CreateAsst();
extern __declspec(dllexport) void DestoryAsst(asst::Assistance* p_asst);
extern __declspec(dllexport) bool AsstCatchSimulator(asst::Assistance* p_asst);
extern __declspec(dllexport) void AsstStart(asst::Assistance* p_asst, const char* task);
extern __declspec(dllexport) void AsstStop(asst::Assistance* p_asst);
extern __declspec(dllexport) bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value);
#ifdef __cplusplus
}
#endif

View File

@@ -1,9 +1,45 @@
#pragma once
#include <string>
#include "json_object.h"
#include <unordered_map>
#include <vector>
namespace asst {
struct HandleInfo {
std::string className;
std::string windowName;
};
struct SimulatorInfo {
std::vector<HandleInfo> window;
std::vector<HandleInfo> view;
std::vector<HandleInfo> control;
int width = 0;
int height = 0;
int xOffset = 0;
int yOffset = 0;
};
enum class TaskType {
ClickSelf,
ClickRand,
DoNothing,
Stop
};
struct TaskInfo {
std::string filename;
double threshold = 0;
TaskType type;
std::vector<std::string> next;
unsigned int exec_times = 0;
unsigned int max_times = UINT_MAX;
};
struct Options {
std::string delayType;
int delayFixedTime = 0;
bool cache = false;
};
class Configer
{
public:
@@ -12,9 +48,13 @@ namespace asst {
static bool reload();
static std::string getCurDir();
static std::string getResDir();
static json::object tasksJson;
static json::object handleJson;
static json::object optionsJson;
static std::string m_version;
static Options m_options;
static std::unordered_map<std::string, TaskInfo> m_tasks;
static std::unordered_map<std::string, SimulatorInfo> m_handles;
static bool setParam(const std::string& type, const std::string& param, const std::string& value);
private:
Configer() = default;

View File

@@ -23,6 +23,7 @@ namespace asst {
// return tuple< algorithmType, suitability, scaled asst::rect>
std::tuple<int, double, asst::Rect> findImage(const cv::Mat& image, const std::string& templ, double threshold = 0.99);
void clear_cache();
private:
cv::Mat image2Hist(const cv::Mat& src);
double imageHistComp(const cv::Mat& src, const cv::MatND& hist);
@@ -33,9 +34,9 @@ namespace asst {
// return pair< suitability, raw opencv::point>
std::pair<double, cv::Point> findImage(const cv::Mat& cur, const cv::Mat& templ);
std::unordered_map<std::string, cv::Mat> m_matMap;
std::unordered_map<std::string, cv::Mat> m_mat_map;
bool m_use_cache = true;
std::unordered_map<std::string, std::pair<cv::Rect, cv::Mat>> m_cacheMap;
std::unordered_map<std::string, std::pair<cv::Rect, cv::Mat>> m_cache_map;
};
}

View File

@@ -10,20 +10,22 @@ Assistance::Assistance()
{
Configer::reload();
m_Ider = std::make_shared<Identify>();
for (auto&& pair : Configer::tasksJson)
m_pIder = std::make_shared<Identify>();
for (auto&& [name, info] : Configer::m_tasks)
{
m_Ider->addImage(pair.first, Configer::getResDir() + pair.second["filename"].as_string());
m_pIder->addImage(name, Configer::getResDir() + info.filename);
}
m_Ider->setUseCache(Configer::optionsJson["cache"].as_boolean());
m_pIder->setUseCache(Configer::m_options.cache);
m_working_thread = std::thread(working_proc, this);
m_working_thread = std::thread(workingProc, this);
}
Assistance::~Assistance()
{
m_pWindow->showWindow();
if (m_pWindow != nullptr) {
m_pWindow->showWindow();
}
m_thread_exit = true;
m_thread_running = false;
@@ -38,7 +40,7 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
{
stop();
auto create_handles = [&](const std::string name) -> bool {
auto create_handles = [&](const std::string& name) -> bool {
m_pWindow = std::make_shared<WinMacro>(name, HandleType::Window);
m_pView = std::make_shared<WinMacro>(name, HandleType::View);
m_pCtrl = std::make_shared<WinMacro>(name, HandleType::Control);
@@ -51,7 +53,7 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
std::unique_lock<std::mutex> lock(m_mutex);
if (simulator_name.empty()) {
for (auto&& [name, value] : Configer::handleJson)
for (auto&& [name, value] : Configer::m_handles)
{
ret = create_handles(name);
if (ret) {
@@ -64,22 +66,25 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
ret = create_handles(simulator_name);
}
if (ret && m_pWindow->resizeWindow()) {
m_inited = true;
return cor_name;
}
else {
m_inited = false;
return std::nullopt;
}
}
void Assistance::start()
void Assistance::start(const std::string& task)
{
if (m_thread_running) {
if (m_thread_running || !m_inited) {
return;
}
std::unique_lock<std::mutex> lock(m_mutex);
m_pIder->clear_cache();
m_next_tasks.clear();
m_next_tasks.emplace_back("Begin");
m_next_tasks.emplace_back(task);
m_thread_running = true;
m_condvar.notify_one();
}
@@ -90,23 +95,28 @@ void Assistance::stop()
m_thread_running = false;
m_next_tasks.clear();
m_pIder->clear_cache();
}
void Assistance::working_proc(Assistance* pThis)
bool Assistance::setParam(const std::string& type, const std::string& param, const std::string& value)
{
return Configer::setParam(type, param, value);
}
void Assistance::workingProc(Assistance* pThis)
{
while (!pThis->m_thread_exit) {
std::unique_lock<std::mutex> lock(pThis->m_mutex);
if (pThis->m_thread_running) {
auto curImg = pThis->m_pView->getImage(pThis->m_pView->getWindowRect());
std::string matched_task;
Rect matched_rect;
for (auto&& task_jstr : pThis->m_next_tasks) {
std::string task_name = task_jstr.as_string();
double threshold = Configer::tasksJson[task_name]["threshold"].as_double();
auto&& [algorithm, value, rect] = pThis->m_Ider->findImage(curImg, task_name, threshold);
DebugTrace("%-20s %f", task_name.c_str(), value);
if ( algorithm == 0 ||
for (auto&& task_name : pThis->m_next_tasks) {
double threshold = Configer::m_tasks[task_name].threshold;
auto&& [algorithm, value, rect] = pThis->m_pIder->findImage(curImg, task_name, threshold);
DebugTrace("%-20s Type:%d, Value:%f", task_name.c_str(), algorithm, value);
if (algorithm == 0 ||
(algorithm == 1 && value >= threshold)
|| (algorithm == 2 && value >= 0.9999)) {
matched_task = task_name;
@@ -116,36 +126,49 @@ void Assistance::working_proc(Assistance* pThis)
}
if (!matched_task.empty()) {
auto task = Configer::tasksJson[matched_task].as_object();
std::string opType = task["type"].as_string();
DebugTraceInfo("Matched: %s, type: %s", matched_task.c_str(), opType.c_str());
auto task = Configer::m_tasks[matched_task];
DebugTraceInfo("Matched: %s, Type: %d", matched_task.c_str(), task.type);
if (opType == "clickSelf") {
switch (task.type) {
case TaskType::ClickSelf:
if (task.exec_times >= task.max_times) {
pThis->m_thread_running = false;
pThis->m_next_tasks.clear();
continue;
}
pThis->m_pCtrl->clickRange(matched_rect);
}
else if (opType == "clickRand") {
++task.exec_times;
break;
case TaskType::ClickRand:
pThis->m_pCtrl->clickRange(pThis->m_pCtrl->getWindowRect());
}
else if (opType == "doNothing") {
// do nothing
}
else if (opType == "stop") {
DebugTrace("opType == stop");
break;
case TaskType::DoNothing:
break;
case TaskType::Stop:
DebugTrace("TaskType is Stop");
pThis->m_thread_running = false;
pThis->m_next_tasks.clear();
continue;
}
else {
DebugTraceError("Unknow option type: %s", opType.c_str());
break;
default:
DebugTraceError("Unknown option type: %d", task.type);
break;
}
pThis->m_next_tasks = Configer::tasksJson[matched_task]["next"].as_array();
DebugTrace("Next: %s", pThis->m_next_tasks.to_string().c_str());
pThis->m_next_tasks = Configer::m_tasks[matched_task].next;
std::string nexts;
for (auto&& name : pThis->m_next_tasks) {
nexts += name + ",";
}
if (nexts.back() == ',') {
nexts.pop_back();
}
DebugTrace("Next: %s", nexts.c_str());
}
pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(Configer::optionsJson["delay"]["fixedTime"].as_integer()));
pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(Configer::m_options.delayFixedTime));
}
else {
pThis->m_condvar.wait(lock);
}
}
}
}

View File

@@ -0,0 +1,58 @@
#include "AsstCaller.h"
asst::Assistance* CreateAsst()
{
return new asst::Assistance();
}
void DestoryAsst(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return;
}
delete p_asst;
p_asst = NULL;
}
bool AsstCatchSimulator(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return false;
}
auto ret = p_asst->setSimulator();
if (ret) {
return true;
}
else {
return false;
}
}
void AsstStart(asst::Assistance* p_asst, const char* task)
{
if (p_asst == NULL) {
}
p_asst->start(task);
}
void AsstStop(asst::Assistance* p_asst)
{
if (p_asst == NULL) {
return;
}
p_asst->stop();
}
bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value)
{
if (p_asst == NULL) {
return false;
}
p_asst->setParam(type, param, value);
}

View File

@@ -2,17 +2,19 @@
#include <fstream>
#include <sstream>
#include <algorithm>
#include <Windows.h>
#include "json.h"
#include "AsstDef.h"
using namespace asst;
json::object Configer::tasksJson;
json::object Configer::handleJson;
json::object Configer::optionsJson;
std::string Configer::m_curDir;
std::string Configer::m_version;
Options Configer::m_options;
std::unordered_map<std::string, TaskInfo> Configer::m_tasks;
std::unordered_map<std::string, SimulatorInfo> Configer::m_handles;
bool Configer::reload()
{
@@ -32,11 +34,122 @@ bool Configer::reload()
}
auto root = std::move(ret).value();
tasksJson = root["tasks"].as_object();
handleJson = root["handle"].as_object();
optionsJson = root["options"].as_object();
try {
m_version = root["version"].as_string();
auto options_obj = root["options"].as_object();
m_options.delayType = options_obj["delay"]["type"].as_string();
m_options.delayFixedTime = options_obj["delay"]["fixedTime"].as_integer();
m_options.cache = options_obj["cache"].as_boolean();
auto tasks_obj = root["tasks"].as_object();
for (auto&& [name, task_json] : tasks_obj) {
TaskInfo task_info;
task_info.filename = task_json["filename"].as_string();
task_info.threshold = task_json["threshold"].as_double();
std::string type = task_json["type"].as_string();
std::transform(type.begin(), type.end(), type.begin(), std::tolower);
if (type == "clickself") {
task_info.type = TaskType::ClickSelf;
}
else if (type == "clickrand") {
task_info.type = TaskType::ClickRand;
}
else if (type == "donothing" || type.empty()) {
task_info.type = TaskType::DoNothing;
}
else if (type == "stop") {
task_info.type = TaskType::Stop;
}
else {
DebugTraceError("Task: %s 's type error: %s", name.c_str(), type.c_str());
return false;
}
if (task_json.as_object().exist("maxTimes")) {
task_info.max_times = task_json["maxTimes"].as_integer();
}
auto next_arr = task_json["next"].as_array();
for (auto&& name : next_arr) {
task_info.next.emplace_back(name.as_string());
}
m_tasks.emplace(name, task_info);
}
auto handle_obj = root["handle"].as_object();
for (auto&& [name, simulator_json] : handle_obj) {
SimulatorInfo simulator_info;
auto window_arr = simulator_json["window"].as_array();
for (auto&& info : window_arr) {
HandleInfo handle_info;
handle_info.className = info["class"].as_string();
handle_info.windowName = info["window"].as_string();
simulator_info.window.emplace_back(handle_info);
}
auto view_arr = simulator_json["view"].as_array();
for (auto&& info : view_arr) {
HandleInfo handle_info;
handle_info.className = info["class"].as_string();
handle_info.windowName = info["window"].as_string();
simulator_info.view.emplace_back(handle_info);
}
auto ctrl_arr = simulator_json["control"].as_array();
for (auto&& info : ctrl_arr) {
HandleInfo handle_info;
handle_info.className = info["class"].as_string();
handle_info.windowName = info["window"].as_string();
simulator_info.control.emplace_back(handle_info);
}
simulator_info.width = simulator_json["width"].as_integer();
simulator_info.height = simulator_json["height"].as_integer();
simulator_info.xOffset = simulator_json["xOffset"].as_integer();
simulator_info.yOffset = simulator_json["yOffset"].as_integer();
m_handles.emplace(name, simulator_info);
}
}
catch (json::exception& e) {
DebugTraceError("Load config json error!: %s", e.what());
return false;
}
return true;
}
bool Configer::setParam(const std::string& type, const std::string& param, const std::string& value)
{
if (type == "task.type") {
if (m_tasks.find(param) == m_tasks.cend()) {
return false;
}
auto& task_info = m_tasks[param];
std::string type = value;
std::transform(type.begin(), type.end(), type.begin(), std::tolower);
if (type == "clickself") {
task_info.type = TaskType::ClickSelf;
}
else if (type == "clickrand") {
task_info.type = TaskType::ClickRand;
}
else if (type == "donothing" || type.empty()) {
task_info.type = TaskType::DoNothing;
}
else if (type == "stop") {
task_info.type = TaskType::Stop;
}
else {
DebugTraceError("Task: %s 's type error: %s", param.c_str(), type.c_str());
return false;
}
}
else if (type == "task.maxTimes") {
if (m_tasks.find(param) == m_tasks.cend()) {
return false;
}
m_tasks[param].max_times = std::stoi(value);
}
return true;
}
@@ -54,4 +167,4 @@ std::string Configer::getCurDir()
std::string Configer::getResDir()
{
return getCurDir() + "resource\\";
}
}

View File

@@ -12,7 +12,7 @@ bool Identify::addImage(const std::string& name, const std::string& path)
if (mat.empty()) {
return false;
}
m_matMap.emplace(name, mat);
m_mat_map.emplace(name, mat);
return true;
}
@@ -22,7 +22,7 @@ void Identify::setUseCache(bool b) noexcept
m_use_cache = true;
}
else {
m_cacheMap.clear();
m_cache_map.clear();
m_use_cache = false;
}
}
@@ -69,30 +69,33 @@ std::pair<double, cv::Point> Identify::findImage(const cv::Mat& image, const cv:
std::tuple<int, double, asst::Rect> Identify::findImage(const Mat& cur, const std::string& templ, double threshold)
{
if (m_matMap.find(templ) == m_matMap.cend()) {
if (m_mat_map.find(templ) == m_mat_map.cend()) {
return { 0, 0, asst::Rect() };
}
if (m_use_cache && m_cacheMap.find(templ) != m_cacheMap.cend()) {
DebugTrace("Identify | %s get cache", templ.c_str());
auto&& [rect, hist] = m_cacheMap.at(templ);
if (m_use_cache && m_cache_map.find(templ) != m_cache_map.cend()) {
auto&& [rect, hist] = m_cache_map.at(templ);
double value = imageHistComp(cur(rect), hist);
return { 2, value, cvRect2Rect(rect).center_zoom(0.8) };
}
else {
auto&& templ_mat = m_matMap.at(templ);
auto&& templ_mat = m_mat_map.at(templ);
auto&& [value, point] = findImage(cur, templ_mat);
cv::Rect raw_rect(point.x, point.y, templ_mat.cols, templ_mat.rows);
if (m_use_cache && value >= threshold) {
DebugTrace("Identify | %s add to cache", templ.c_str());
m_cacheMap.emplace(templ, std::make_pair(raw_rect, image2Hist(cur(raw_rect))));
m_cache_map.emplace(templ, std::make_pair(raw_rect, image2Hist(cur(raw_rect))));
}
return { 1, value, cvRect2Rect(raw_rect).center_zoom(0.8) };
}
}
void Identify::clear_cache()
{
m_cache_map.clear();
}
/*
std::pair<double, asst::Rect> Identify::findImageWithFile(const cv::Mat& cur, const std::string& filename)
{

View File

@@ -28,21 +28,21 @@ bool WinMacro::captured() const noexcept
bool WinMacro::findHandle()
{
json::array handle_arr;
json::value simulator_json = Configer::handleJson[m_simulator_name];
std::vector<HandleInfo> handle_vec;
auto&& info = Configer::m_handles[m_simulator_name];
switch (m_handle_type) {
case HandleType::Window:
m_width = simulator_json["Width"].as_integer();
m_height = simulator_json["Height"].as_integer();
handle_arr = simulator_json["Window"].as_array();
m_width = info.width;
m_height = info.height;
handle_vec = info.window;
break;
case HandleType::View:
handle_arr = simulator_json["View"].as_array();
handle_vec = info.view;
break;
case HandleType::Control:
m_xOffset = simulator_json["xOffset"].as_integer();
m_yOffset = simulator_json["yOffset"].as_integer();
handle_arr = simulator_json["Control"].as_array();
m_xOffset = info.xOffset;
m_yOffset = info.yOffset;
handle_vec = info.control;
break;
default:
DebugTraceError("Handle type error!: %d", m_handle_type);
@@ -50,22 +50,20 @@ bool WinMacro::findHandle()
}
m_handle = NULL;
for (auto&& obj : handle_arr)
for (auto&& handle_info : handle_vec)
{
wchar_t* class_wbuff = NULL;
std::string class_str = obj["class"].as_string();
if (!class_str.empty()) {
size_t class_len = (class_str.size() + 1) * 2;
if (!handle_info.className.empty()) {
size_t class_len = (handle_info.className.size() + 1) * 2;
class_wbuff = new wchar_t[class_len];
::MultiByteToWideChar(CP_UTF8, 0, class_str.c_str(), -1, class_wbuff, class_len);
::MultiByteToWideChar(CP_UTF8, 0, handle_info.className.c_str(), -1, class_wbuff, class_len);
}
wchar_t* window_wbuff = NULL;
std::string window_str = obj["window"].as_string();
if (!window_str.empty()) {
size_t window_len = (window_str.size() + 1) * 2;
if (!handle_info.windowName.empty()) {
size_t window_len = (handle_info.windowName.size() + 1) * 2;
window_wbuff = new wchar_t[window_len];
memset(window_wbuff, 0, window_len);
::MultiByteToWideChar(CP_UTF8, 0, window_str.c_str(), -1, window_wbuff, window_len);
::MultiByteToWideChar(CP_UTF8, 0, handle_info.windowName.c_str(), -1, window_wbuff, window_len);
}
m_handle = ::FindWindowExW(m_handle, NULL, class_wbuff, window_wbuff);

6
MeoAsstGui/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

9
MeoAsstGui/App.xaml Normal file
View File

@@ -0,0 +1,9 @@
<Application x:Class="MeoAsstGui.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MeoAsstGui"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

17
MeoAsstGui/App.xaml.cs Normal file
View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace MeoAsstGui
{
/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,19 @@
<Window x:Class="MeoAsstGui.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MeoAsstGui"
mc:Ignorable="d"
Title="MeoAssistance-明日方舟辅助" Height="500" Width="400">
<Grid>
<CheckBox x:Name="checkBox_useMedicine" Content="吃理智药" HorizontalAlignment="Left" Margin="50,100,0,0" VerticalAlignment="Top" Checked="checkBox_useMedicine_Checked" Unchecked="checkBox_useMedicine_Checked" IsChecked="True"/>
<CheckBox x:Name="checkBox_useStone" Content="吃石头" HorizontalAlignment="Left" Margin="50,150,0,0" VerticalAlignment="Top" Checked="checkBox_useStone_Checked" Unchecked="checkBox_useStone_Checked"/>
<TextBox x:Name="textBox_useStone" HorizontalAlignment="Left" Height="23" Margin="112,148,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_useStone_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
<Label x:Name="label_stoneNumber" Content="颗" HorizontalAlignment="Left" Margin="164,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-5.771,-6.291"/>
<Button x:Name="button_startSanity" Content="开始刷理智" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,280,0,0" VerticalAlignment="Top" Width="300" Height="50" Click="button_Click_stop"/>
<Label x:Name="catch_status" Content="" HorizontalAlignment="Left" Margin="50,30,0,0" VerticalAlignment="Top"/>
<Button x:Name="button_visit" Content="访问基建" HorizontalAlignment="Left" Margin="230,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
</Grid>
</Window>

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
namespace MeoAsstGui
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
[DllImport("MeoAssistance.dll")] static public extern IntPtr CreateAsst();
[DllImport("MeoAssistance.dll")] static public extern void DestoryAsst(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern bool AsstCatchSimulator(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern void AsstStart(IntPtr ptr, string task);
[DllImport("MeoAssistance.dll")] static public extern void AsstStop(IntPtr ptr);
[DllImport("MeoAssistance.dll")] static public extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
private IntPtr p_asst;
public MainWindow()
{
InitializeComponent();
p_asst = CreateAsst();
}
~MainWindow()
{
DestoryAsst(p_asst);
}
private void button_Click_startSanity(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchSimulator(p_asst);
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "SanityBegin");
}
private void button_Click_stop(object sender, RoutedEventArgs e)
{
AsstStop(p_asst);
catch_status.Content = "";
}
private void checkBox_useMedicine_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_useMedicine.IsChecked == true)
{
AsstSetParam(p_asst, "task.type", "UseMedicine", "doNothing");
}
else
{
AsstSetParam(p_asst, "task.type", "UseMedicine", "stop");
}
}
private void textBox_useStone_TextChanged(object sender, TextChangedEventArgs e)
{
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", textBox_useStone.Text);
}
private void checkBox_useStone_Checked(object sender, RoutedEventArgs e)
{
if (checkBox_useMedicine.IsChecked == true)
{
AsstSetParam(p_asst, "task.type", "UseStone", "doNothing");
}
else
{
AsstSetParam(p_asst, "task.type", "UseStone", "stop");
}
}
private void button_Click_visit(object sender, RoutedEventArgs e)
{
bool catched = AsstCatchSimulator(p_asst);
catch_status.Content = "捕获模拟器窗口:" + catched;
AsstStart(p_asst, "VisitBegin");
}
}
}

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>MeoAsstGui</RootNamespace>
<AssemblyName>MeoAsstGui</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("MeoAsstGui")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MeoAsstGui")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
//若要开始生成可本地化的应用程序,请设置
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
//例如,如果您在源文件中使用的是美国英语,
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
//对以下 NeutralResourceLanguage 特性的注释。 更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
//(未在页面中找到资源时使用,
//或应用程序资源字典中找到时使用)
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
//(未在页面中找到资源时使用,
//、应用程序或任何主题专用资源字典中找到时使用)
)]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本: 4.0.30319.42000
//
// 对此文件的更改可能导致不正确的行为,如果
// 重新生成代码,则所做更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace MeoAsstGui.Properties
{
/// <summary>
/// 强类型资源类,用于查找本地化字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// 返回此类使用的缓存 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MeoAsstGui.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MeoAsstGui.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -4,11 +4,16 @@ A game assistance for Arknights
一款明日方舟的游戏辅助供PC端安卓模拟器使用龟速开发中……
![截图](README/1.png)
## 功能介绍
- 目前版本支持自动刷完所有体力+自动吃完体力药
- 支持自动刷完理智
- 支持自动吃完体力药
- 支持根据设置自动吃石头
- 刷完后程序会自动停止
- 代理失败会自动放弃本次行动
- 支持自动访问好友基建
- 所有操作,都是点击按钮内随机位置,且模拟泊松分布,不会像鼠标宏一样一直是同一个点,没有封号风险
~~(虽然好像也没听说过谁用鼠标宏被封号的)~~
- 模拟器窗口可以被遮挡,即使全屏看视频、玩游戏,也完全不影响辅助运行
@@ -45,9 +50,24 @@ A game assistance for Arknights
## 使用说明
1. 使用支持的模拟器打开明日方舟,进入有**蓝色的开始行动按钮**的界面
2. 解压压缩包,**使用管理员权限**,打开"Sanity.exe"
3. 目前只有最基本的功能,刷完体力+体力药就会自动停了……
### 基本说明
1. 使用支持的模拟器打开明日方舟
2. 解压压缩包,**使用管理员权限**,打开"MeoAsstGui.exe"
3. 注意:运行期间,模拟器窗口可以被遮挡,全屏玩游戏、看视频等,完全不影响,但是!!模拟器不能最小化!!!
### 刷理智
1. 明日方舟打开**蓝色开始按钮**的界面
1. 根据你的需要勾选"吃理智药"和"吃石头"
2. 点击"开始刷理智"
3. 刷完了会自动停止的
### 访问好友基建
1. 明日方舟处于任意界面均可,会自动帮你点过去
2. 点击"访问基建"
3. 达到10次上限或者所有可访问的好友都访问完了就会自动停的
## Todo
@@ -55,6 +75,10 @@ A game assistance for Arknights
- [ ] 功能
- [ ] 图形化界面
- [x] 基本图形化界面
- [ ] 图形化界面进一步完善
- [ ] 日志打印,错误提示
- [ ] 使模拟器窗口不可见的按钮
- [ ] 刷理智
- [x] 支持剿灭
- [x] 支持使模拟器窗口不可见
@@ -63,26 +87,29 @@ A game assistance for Arknights
- [x] 支持等级提升
- [x] 支持自动勾选代理指挥
- [ ] 支持刷指定次数
- [ ] 自动吃石头(根据设置,指定数量)
- [x] 自动吃石头(根据设置,指定数量)
- [ ] 支持凌晨4点更新数据
- [ ] 结束界面自动截图,可用于上传企鹅物流
- [ ] 持续监视理智,一有就自动刷掉
- [ ] 模拟器被最小化了,给出提示
- [x] 支持更多模拟器
- [ ] 信用访问
- [x] 信用访问
- [ ] 基建收菜
- [ ] 当前公招可能干员一览
- [x] 算法
- [x] 更换算法为模板匹配找图,而不是当前的区域相似度对比
- [x] 优化算法效率,添加缓存功能
- [x] 优化任务队列,减少不必要的计算
- [ ] 进一步优化任务队列效率
- [x] 其他
- [x] 尝试减小程序体积
## 致谢
感谢以下开源库/API
感谢以下开源库/免费API
- WinAPI
- OpenCV
- MeoJson
- WPF

BIN
README/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -17,7 +17,7 @@ int main(int argc, char** argv)
}
DebugTraceInfo("Start");
asst.start();
asst.start("SanityBegin");
getchar();

Submodule meojson updated: b530ddcffa...e66deff929

BIN
resource/Friends.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
resource/FriendsList.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
resource/RationToday.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 KiB

BIN
resource/Return.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
resource/StartToVisit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
resource/VisitLimited.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
resource/VisitNext.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
resource/VisitNextBlack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,5 +1,5 @@
{
"version": 0.2,
"version": "0.3",
"options": {
"delay": {
"type": "fixedTime",
@@ -9,7 +9,19 @@
},
"handle": {
"BlueStacks": {
"Control": [
"window": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
}
],
"view": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
}
],
"control": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
@@ -23,49 +35,49 @@
"window": "BlueStacks Android PluginAndroid"
}
],
"View": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
}
],
"Window": [
{
"class": "BS2CHINAUI",
"window": "BlueStacks App Player"
}
],
"Width": 1294,
"Height": 773,
"width": 1294,
"height": 773,
"xOffset": -7,
"yOffset": -47
},
"Nox": {
"Control": [
"window": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"View": [
"view": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"Window": [
"control": [
{
"class": "Qt5QWindowIcon",
"window": "夜神模拟器"
}
],
"Width": 1298,
"Height": 754,
"width": 1298,
"height": 754,
"xOffset": 0,
"yOffset": -32
},
"LDPlayer": {
"Control": [
"window": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"view": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"control": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
@@ -75,25 +87,25 @@
"window": "TheRender"
}
],
"View": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"Window": [
{
"class": "LDPlayerMainFrame",
"window": "雷电模拟器"
}
],
"Width": 1304,
"Height": 756,
"width": 1304,
"height": 756,
"xOffset": 0,
"yOffset": -35
},
"XYAZ": {
"Control": [
"window": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"view": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"control": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
@@ -103,25 +115,25 @@
"window": "MainWindowWindow"
}
],
"View": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"Window": [
{
"class": "Qt5QWindowIcon",
"window": "逍遥模拟器"
}
],
"Width": 1282,
"Height": 769,
"width": 1282,
"height": 769,
"xOffset": 0,
"yOffset": -47
},
"Tencent": {
"Control": [
"window": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"view": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"control": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
@@ -131,26 +143,14 @@
"window": "AEngineRenderWindow"
}
],
"View": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"Window": [
{
"class": "TXGuiFoundation",
"window": "腾讯手游助手"
}
],
"Width": 1282,
"Height": 769,
"width": 1282,
"height": 769,
"xOffset": 0,
"yOffset": -42
}
},
"tasks": {
"Begin": {
"SanityBegin": {
"filename": "",
"threshold": 0,
"type": "doNothing",
@@ -230,7 +230,7 @@
"UseStone": {
"filename": "UseStone.png",
"threshold": 0.99,
"type": "stop",
"type": "doNothing",
"next": [
"StoneConfirm"
]
@@ -239,6 +239,7 @@
"filename": "MedicineConfirm.png",
"threshold": 0.98,
"type": "clickSelf",
"maxTimes": 0,
"next": [
"StartButton1"
]
@@ -258,6 +259,74 @@
"next": [
"Random"
]
},
"VisitBegin": {
"filename": "",
"threshold": 0,
"type": "doNothing",
"next": [
"Friends",
"FriendsList",
"StartToVisit",
"VisitNext",
"VisitNextBlack",
"Return"
]
},
"Return": {
"filename": "Return.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"Friends",
"Return"
]
},
"Friends": {
"filename": "Friends.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"FriendsList"
]
},
"FriendsList": {
"filename": "FriendsList.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"StartToVisit"
]
},
"StartToVisit": {
"filename": "StartToVisit.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"VisitNext"
]
},
"VisitNext": {
"filename": "VisitNext.png",
"threshold": 0.98,
"type": "clickSelf",
"next": [
"VisitLimited",
"VisitNext",
"VisitNextBlack"
]
},
"VisitLimited": {
"filename": "VisitLimited.png",
"threshold": 0.65,
"type": "stop",
"next": []
},
"VisitNextBlack": {
"filename": "VisitNextBlack.png",
"threshold": 0.98,
"type": "stop",
"next": []
}
}
}