Some works for #124

This commit is contained in:
Namhyeon Go 2024-07-29 15:04:22 +09:00
parent b5af648512
commit f73b180329
4 changed files with 124 additions and 60 deletions

View File

@ -1,51 +1,85 @@
// this is prototype code /*
// https://github.com/gnh1201/welsonjs * WelsonJS.Service
*
* filename:
* ScreenTimer.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*/
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.ServiceProcess;
using System.Timers;
using System.Windows.Forms; using System.Windows.Forms;
using WelsonJS.Service; using WelsonJS.Service;
public class TemplateMatching public class ScreenTimer : System.Timers.Timer
{ {
public void Test(string workingDirectory) private static List<Bitmap> templateImages = new List<Bitmap>();
private string templateDirectory;
public string WorkingDirectory { get; set; }
public ServiceBase Parent { get; set; }
public class MatchedResult
{ {
string templateFolderPath = Path.Combine(workingDirectory, "assets/img/templates"); public string FileName;
public int ScreenNumber;
public Point Location;
public double MaxCorrelation;
}
// Load all template images public ScreenTimer()
List<Bitmap> templateImages = LoadTemplateImages(templateFolderPath); {
Elapsed += OnTimeElapsed;
// try template matching templateDirectory = Path.Combine(WorkingDirectory, "assets/img/templates");
List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)> results = LoadTemplateImages();
CaptureAndMatchAllScreens(templateImages); }
// print results private void OnTimeElapsed(object sender, ElapsedEventArgs e)
foreach (var result in results) {
List<MatchedResult> matchedResults = CaptureAndMatchAllScreens();
ServiceMain svc = (ServiceMain)Parent;
matchedResults.ForEach(result =>
{ {
Console.WriteLine($"Template: {result.FileName}, Screen: {result.ScreenNumber}, " + svc.Log(svc.DispatchServiceEvent("screenTime", new object[] {
$"Location: (x: {result.Location.X}, y: {result.Location.Y}), " + result.FileName,
$"Max Correlation: {result.MaxCorrelation}"); result.ScreenNumber,
result.Location.X,
result.Location.Y,
result.MaxCorrelation
}));
});
}
public void LoadTemplateImages()
{
string[] imageFiles = Directory.GetFiles(templateDirectory, "*.png");
foreach (string file in imageFiles)
{
templateImages.Add(new Bitmap(file));
} }
} }
public static List<Bitmap> LoadTemplateImages(string folderPath) public List<MatchedResult> CaptureAndMatchAllScreens()
{ {
var templates = new List<Bitmap>(); var results = new List<MatchedResult>();
var files = Directory.GetFiles(folderPath, "*.png");
foreach (var file in files)
{
templates.Add(new Bitmap(file));
}
return templates;
}
public static List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)>
CaptureAndMatchAllScreens(List<Bitmap> templateImages)
{
var results = new List<(string FileName, int ScreenNumber, Point Location, double MaxCorrelation)>();
for (int i = 0; i < Screen.AllScreens.Length; i++) for (int i = 0; i < Screen.AllScreens.Length; i++)
{ {
@ -57,14 +91,20 @@ public class TemplateMatching
Point matchLocation = FindTemplate(mainImage, templateImage, out double maxCorrelation); Point matchLocation = FindTemplate(mainImage, templateImage, out double maxCorrelation);
string templateFileName = templateImage.Tag as string; string templateFileName = templateImage.Tag as string;
results.Add((templateFileName, i, matchLocation, maxCorrelation)); results.Add(new MatchedResult
{
FileName = templateFileName,
ScreenNumber = i,
Location = matchLocation,
MaxCorrelation = maxCorrelation
});
} }
} }
return results; return results;
} }
public static Bitmap CaptureScreen(Screen screen) public Bitmap CaptureScreen(Screen screen)
{ {
Rectangle screenSize = screen.Bounds; Rectangle screenSize = screen.Bounds;
Bitmap bitmap = new Bitmap(screenSize.Width, screenSize.Height); Bitmap bitmap = new Bitmap(screenSize.Width, screenSize.Height);
@ -77,7 +117,7 @@ public class TemplateMatching
return bitmap; return bitmap;
} }
public static Point FindTemplate(Bitmap mainImage, Bitmap templateImage, out double maxCorrelation) public Point FindTemplate(Bitmap mainImage, Bitmap templateImage, out double maxCorrelation)
{ {
int mainWidth = mainImage.Width; int mainWidth = mainImage.Width;
int mainHeight = mainImage.Height; int mainHeight = mainImage.Height;
@ -103,7 +143,7 @@ public class TemplateMatching
return bestMatch; return bestMatch;
} }
private static double CalculateCorrelation(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY) private double CalculateCorrelation(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY)
{ {
int templateWidth = templateImage.Width; int templateWidth = templateImage.Width;
int templateHeight = templateImage.Height; int templateHeight = templateImage.Height;

View File

@ -35,6 +35,7 @@ namespace WelsonJS.Service
private static List<Timer> timers; private static List<Timer> timers;
private string workingDirectory; private string workingDirectory;
private string scriptName; private string scriptName;
private bool disabledScreenTimer = false;
private string scriptFilePath; private string scriptFilePath;
private string scriptText; private string scriptText;
private ScriptControl scriptControl; private ScriptControl scriptControl;
@ -52,12 +53,23 @@ namespace WelsonJS.Service
timers = new List<Timer>(); timers = new List<Timer>();
// set default timer // set default timer
Timer timer = new Timer Timer defaultTimer = new Timer
{ {
Interval = 60000 // 1 minute Interval = 60000 // 1 minute
}; };
timer.Elapsed += OnElapsedTime; defaultTimer.Elapsed += OnElapsedTime;
timers.Add(timer); timers.Add(defaultTimer);
// set screen timer
if (!disabledScreenTimer)
{
timers.Add(new ScreenTimer
{
Parent = this,
WorkingDirectory = workingDirectory,
Interval = 1000 // 1 second
});
}
} }
internal void TestStartupAndStop(string[] args) internal void TestStartupAndStop(string[] args)
@ -82,6 +94,10 @@ namespace WelsonJS.Service
case "script-name": case "script-name":
scriptName = entry.Value; scriptName = entry.Value;
break; break;
case "--disable-screen-timer":
disabledScreenTimer = true;
break;
} }
} }
@ -127,7 +143,7 @@ namespace WelsonJS.Service
scriptControl.AddCode(scriptText); scriptControl.AddCode(scriptText);
// initialize // initialize
Log(DispatchServiceEvent(scriptName, "start")); Log(DispatchServiceEvent("start"));
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -152,7 +168,7 @@ namespace WelsonJS.Service
try try
{ {
Log(DispatchServiceEvent(scriptName, "stop")); Log(DispatchServiceEvent("stop"));
scriptControl?.Reset(); scriptControl?.Reset();
} }
catch (Exception ex) catch (Exception ex)
@ -168,7 +184,7 @@ namespace WelsonJS.Service
{ {
try try
{ {
Log(DispatchServiceEvent(scriptName, "elapsedTime")); Log(DispatchServiceEvent("elapsedTime"));
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -176,11 +192,6 @@ namespace WelsonJS.Service
} }
} }
private string DispatchServiceEvent(string name, string eventType)
{
return InvokeScriptMethod("dispatchServiceEvent", name, eventType);
}
private string InvokeScriptMethod(string methodName, params object[] parameters) private string InvokeScriptMethod(string methodName, params object[] parameters)
{ {
if (scriptControl != null) if (scriptControl != null)
@ -195,15 +206,6 @@ namespace WelsonJS.Service
return "void"; return "void";
} }
private void Log(string message)
{
using (StreamWriter writer = new StreamWriter(logFilePath, true))
{
writer.WriteLine($"{DateTime.Now}: {message}");
}
}
private Dictionary<string, string> ParseArguments(string[] args) private Dictionary<string, string> ParseArguments(string[] args)
{ {
var arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); var arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@ -219,12 +221,30 @@ namespace WelsonJS.Service
var value = arg.Substring(index + 1); var value = arg.Substring(index + 1);
arguments[key] = value; arguments[key] = value;
} }
else
{
var key = arg.Substring(2);
arguments[key] = "";
}
} }
} }
return arguments; return arguments;
} }
public void Log(string message)
{
using (StreamWriter writer = new StreamWriter(logFilePath, true))
{
writer.WriteLine($"{DateTime.Now}: {message}");
}
}
public string DispatchServiceEvent(string eventType, object[] args = null)
{
return InvokeScriptMethod("dispatchServiceEvent", scriptName, eventType, args);
}
public string GetWorkingDirectory() public string GetWorkingDirectory()
{ {
return workingDirectory; return workingDirectory;

View File

@ -90,6 +90,9 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ScreenTimer.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ServiceMain.cs"> <Compile Include="ServiceMain.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
@ -104,7 +107,6 @@
<DependentUpon>ProjectInstaller.cs</DependentUpon> <DependentUpon>ProjectInstaller.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TemplateMatching.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<COMReference Include="MSScriptControl"> <COMReference Include="MSScriptControl">

10
app.js
View File

@ -589,7 +589,7 @@ function initializeWindow(name, args, w, h) {
} }
} }
function dispatchServiceEvent(name, eventType) { function dispatchServiceEvent(name, eventType, args) {
var app = require(name); var app = require(name);
// load the service // load the service
@ -597,8 +597,9 @@ function dispatchServiceEvent(name, eventType) {
return (function(action) { return (function(action) {
if (eventType in action) { if (eventType in action) {
try { try {
var f = action[eventType]; return (function(f) {
if (typeof f === "function") return f(); return (typeof f !== "function" ? null : f(args));
})(action[eventType]);
} catch (e) { } catch (e) {
console.error("Exception:", e.message); console.error("Exception:", e.message);
} }
@ -606,7 +607,8 @@ function dispatchServiceEvent(name, eventType) {
})({ })({
start: app.onServiceStart, start: app.onServiceStart,
stop: app.onServiceStop, stop: app.onServiceStop,
elapsedTime: app.onServiceElapsedTime elapsedTime: app.onServiceElapsedTime,
screenTime: app.onServiceScreenTime
}); });
} else { } else {
console.error("Could not find", name + ".js"); console.error("Could not find", name + ".js");