| 
					
				 | 
			
			
				@@ -1,220 +1,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package main 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"fmt" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"log" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"math" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"os" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"os/signal" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"strings" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"time" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"github.com/go-vgo/robotgo" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"gopkg.in/yaml.v3" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"gogs.davte.it/davte/autoclick" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-type Point struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	X int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Y int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (p Point) String() string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return fmt.Sprintf("(%v, %v)", p.X, p.Y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (p Point) Click() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	robotgo.Move(p.X, p.Y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	robotgo.Click("left", false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (p1 *Point) GetDistance(p2 *Point) float64 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return math.Sqrt(math.Pow(float64(p1.X-p2.X), float64(2)) + math.Pow(float64(p1.Y-p2.Y), float64(2))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (p0 *Point) GetDistanceFromClosest(pp ...*Point) float64 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	var minDistance float64 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for index, p := range pp { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if distance := p.GetDistance(p0); index == 0 || distance < minDistance { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			minDistance = distance 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return minDistance 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-type PointGroup struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Name   string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Points []*Point 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-type SavedGroups struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Groups []PointGroup 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func getSavedGroups(yamlFile string) *SavedGroups { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	s := SavedGroups{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	inputFile, err := os.ReadFile(yamlFile) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if err == nil { // No yaml file found 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		err = yaml.Unmarshal(inputFile, &s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			log.Fatalf("%v - Exiting", err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for index, g := range s.Groups { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if index == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Println("Available groups:") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Printf("%v. %v\n", index+1, g.Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return &s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func addSavedGroup(s *SavedGroups) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	g := PointGroup{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	var name string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	var points int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		name = "" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Print("If you want to add a new group of locations, enter a name. Press enter to skip.    ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Scanln(&name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if name == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Printf("How many positions are there in group %v?    ", name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_, err := fmt.Scanln(&points) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Println("I haven't understood, try again...") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			var discard string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Scanln(&discard) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for i := 0; i < points; i++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Printf("Please move your mouse into position %v of %v (group %v)\n", i+1, points, name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			time.Sleep(2 * time.Second) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			x, y := robotgo.GetMousePos() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Printf("Added point (x=%v, y=%v) to %v\n", x, y, name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			p := Point{X: x, Y: y} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			g.Points = append(g.Points, &p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		g.Name = name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		s.Groups = append(s.Groups, g) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func storeSavedGroups(s *SavedGroups, yamlFile string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	d, err := yaml.Marshal(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		log.Fatalf("error: %v", err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	err = os.WriteFile(yamlFile, d, 0644) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		log.Fatalf("error: %v", err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func AbsInt(i int) int { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if i > 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		return i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return -i 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func Oscillator(amplitude int) chan int { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	amplitude-- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	c := make(chan int, 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	i := amplitude 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	go func() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			c <- AbsInt((i%(amplitude*2))-amplitude) + 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			i++ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if i == amplitude*2 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				i = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func StringOscillator(s string, amplitude int) chan string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	c := make(chan string) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	o := Oscillator(amplitude) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	go func() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			c <- strings.Repeat(s, <-o) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func ClickRepeteadly(s *SavedGroups) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for index, g := range s.Groups { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Printf("- Press %v to select %v\n", index+1, g.Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	var choice int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for choice < 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Print("Your selection:    ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_, err := fmt.Scanln(&choice) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Println("I haven't understood, try again...") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			var discard string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Scanln(&discard) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	selection := s.Groups[choice-1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	fmt.Printf("You selected %v. I'll be clicking in the following positions:\n", selection.Name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for index, p := range selection.Points { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Printf("%v - %v\n", index+1, p) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	o := StringOscillator(".", 15) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	var t int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	var minDistance float64 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for _, p := range selection.Points { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			p.Click() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			time.Sleep(100 * time.Millisecond) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Println(<-o) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		time.Sleep(500 * time.Millisecond) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		t = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for t = 0; t < 10; t++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			x, y := robotgo.GetMousePos() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			currentPosition := Point{X: x, Y: y} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			minDistance = currentPosition.GetDistanceFromClosest(selection.Points...) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if minDistance <= 50 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Printf("%v You moved the mouse (distance %.2f), waiting 2 seconds (%v of 10)\n", strings.Repeat("_", 10-t), minDistance, t+1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			time.Sleep(2 * time.Second) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if t >= 10 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			fmt.Println("You stayed away too long, exiting...") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func cleanUp(c chan os.Signal) chan int { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	r := make(chan int) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	go func() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		signal := <-c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Printf("Got signal %v, cleaning up...\n", signal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		r <- 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	}() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return r 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	c := make(chan os.Signal, 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	quit := cleanUp(c) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	signal.Notify(c, os.Interrupt) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	yamlFile := "SavedGroups.yaml" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	s := getSavedGroups(yamlFile) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	addSavedGroup(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	storeSavedGroups(s, yamlFile) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	go ClickRepeteadly(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if <-quit == 1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Println("Exiting...") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		fmt.Println("Unknown error...") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	autoclick.RunAutoClicker() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |