The objective is to create timers for League of Legends. It has jungle camps; each one respawns a certain time after killing it.
For this I want to activate the same function for multiple timers at the same time. If I kill blue buff and wolves at the same time I want timers for both of them (click the blue golem's button for my wolves to get the same timer).
I haven't implemented the wolves button but do have a start button. Clicking the blue button starts my timer, but following it up with a click on start game button just queues it until after first timer finishes.
I looked into the wiki page. But I don't want to stop the running timer; I want to run another at the same time. Are there coding errors, better ways of doing things, etc.? Here is my code:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <Timers.au3>
;==> Set our $font variable
Global $font
$font = "Arial Black"
;==> Create our Graphic User Interface
Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
$mainwindow = GUICreate("Jungle Timers Deluxe", 200, 400)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
$startbutton = GUICtrlCreateButton("Start Game", 50, 10, 70)
$ybluebuff = GUICtrlCreateButton("Ancient Golem (Blue)", 10, 40, 50, 50, $BS_MULTILINE)
$yredbuff = GUICtrlCreateButton("Lizard Elder (Red)", 10, 110, 50, 50, $BS_MULTILINE)
$ywraiths = GUICtrlCreateButton("Lizard Elder (Red)", 10, 180, 50, 50, $BS_MULTILINE)
$ywolves = GUICtrlCreateButton("Lizard Elder (Red)", 10, 250, 50, 50, $BS_MULTILINE)
$ydgolems = GUICtrlCreateButton("Lizard Elder (Red)", 10, 320, 50, 50, $BS_MULTILINE)
$ebluebuff = GUICtrlCreateButton("Ancient Golem (Blue)", 100, 40, 50, 50, $BS_MULTILINE)
$eredbuff = GUICtrlCreateButton("Lizard Elder (Red)", 100, 110, 50, 50, $BS_MULTILINE)
$ewraiths = GUICtrlCreateButton("Lizard Elder (Red)", 100, 180, 50, 50, $BS_MULTILINE)
$ewolves = GUICtrlCreateButton("Lizard Elder (Red)", 100, 250, 50, 50, $BS_MULTILINE)
$edgolems = GUICtrlCreateButton("Lizard Elder (Red)", 100, 320, 50, 50, $BS_MULTILINE)
;==> Create our events
GUICtrlSetOnEvent($startbutton, "StartGame")
GUICtrlSetOnEvent($ybluebuff, "yBlueBuff")
;==> Display our Graphic User Interface.
GUISetState(#SW_SHOW)
While 1
Sleep(1000) ; Idle around
WEnd
Func yBlueBuff()
Dim $bluetimer = 10
$i = 1
$ybb = GUICtrlCreateLabel("Your Blue Buff:", 10, 40)
GUICtrlDelete($ybluebuff)
$ybblabel = GUICtrlCreateLabel($i, 15, 60, 50, 40)
While $i <= $bluetimer
GUICtrlDelete($ybblabel)
If $i >= 5 Then
$ybblabel = GUICtrlCreateLabel($i, 15, 60, 50, 40)
GUICtrlSetFont(-1, 22, 500, $font)
GUICtrlSetBkColor($ybblabel, 0xFFCCCC)
$i = $i + 1
ElseIf $i < 5 Then
$ybblabel = GUICtrlCreateLabel($i, 15, 60, 50, 40)
GUICtrlSetFont(-1, 22, 500, $font)
$i = $i + 1
EndIf
Sleep(1000)
WEnd
GUICtrlDelete($ybblabel)
GUICtrlDelete($ybb)
$ybluebuff = GUICtrlCreateButton("Ancient Golem (Blue)", 10, 40, 50, 50, $BS_MULTILINE)
EndFunc ;==>yBlueBuff
Func StartGame()
; Activate your League Window
WinActivate("[CLASS:Notepad]")
; Wait for the Notepad become active - it is titled "Untitled - Notepad" on English systems
WinWaitActive("[CLASS:Notepad]")
; Now that the Notepad window is active type some text
Send("{ENTER}Baron spawns in 15, Dragon spawns at 2:30{ENTER}")
Sleep(500)
Send("{ENTER}Wraiths/Wolves/Double Golems spawn at 1:40. Red & Blue spawn at 1:55{ENTER}")
Sleep(500)
EndFunc ;==>StartGame
Func CLOSEClicked()
;Note: at this point #GUI_CTRLID would equal $GUI_EVENT_CLOSE,
;and #GUI_WINHANDLE would equal $mainwindow
MsgBox(0, "GUI Event", "Thanks for using Jungle Timers Deluxe!")
Exit
EndFunc ;==>CLOSEClicked
; Finished!
I built this off the Notepad example tutorials and use Notepad because it is easier to debug.
AutoIt does not support running two functions simultaneously, otherwise known as multithreading.
Here is their explanation: AutoItNotOnToDoList
In order for your program to work, you would have to be able to constantly monitor whether or not a button is being pressed and at the same time execute the functions that are called by the buttons.
Although it is not technically mulithreading, a workaround for this problem is running multiple scripts at the same time.
Are there ... better ways of doing things, etc.?
Example demonstrating multiple timers (and responsive GUI) :
#include <GUIConstantsEx.au3>; $GUI_EVENT_CLOSE
#include <Timers.au3>
Global Enum $TMR_NAME, _
$TMR_TIME, _
$TMR_STAMP, _
$TMR_STATE, _
$TMR_PROGR, _
$TMR_BTN, _
$TMR__ENUM
Global $g_aTimer[3][$TMR__ENUM]
$g_aTimer[0][$TMR_NAME] = 'Timer A'
$g_aTimer[0][$TMR_TIME] = 60
$g_aTimer[1][$TMR_NAME] = 'Timer B'
$g_aTimer[1][$TMR_TIME] = 30
$g_aTimer[2][$TMR_NAME] = 'Timer C'
$g_aTimer[2][$TMR_TIME] = 10
Main()
Func Main()
Local $iMsg = 0
Local $hGui
GuiMain($hGui, 400, 25)
While True
$iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case Else
ButtonCheck($iMsg)
EndSwitch
TimerUpdate()
WEnd
GUIDelete($hGui)
Exit
EndFunc
Func GuiMain(ByRef $hGui, Const $iWidth, Const $iHeightTimer)
Local Const $iAmount = UBound($g_aTimer)
$hGui = GUICreate(#ScriptName, $iWidth, $iHeightTimer * 2 * $iAmount)
For $i1 = 0 To $iAmount - 1
$g_aTimer[$i1][$TMR_BTN] = GUICtrlCreateButton($g_aTimer[$i1][$TMR_NAME], 0, $i1 * ($iHeightTimer * 2), $iWidth / 2, $iHeightTimer)
$g_aTimer[$i1][$TMR_PROGR] = GUICtrlCreateProgress(0, $iHeightTimer + $i1 * ($iHeightTimer * 2), $iWidth, $iHeightTimer)
Next
GUISetState(#SW_SHOW, $hGui)
EndFunc
Func ButtonCheck(Const $iMsg)
For $i1 = 0 To UBound($g_aTimer) - 1
If $iMsg = $g_aTimer[$i1][$TMR_BTN] Then
$g_aTimer[$i1][$TMR_STATE] = True
$g_aTimer[$i1][$TMR_STAMP] = _Timer_Init()
ExitLoop
EndIf
Next
EndFunc
Func TimerUpdate()
Local $nDiff
For $i1 = 0 To UBound($g_aTimer) - 1
If Not $g_aTimer[$i1][$TMR_STATE] Then ContinueLoop
$nDiff = _Timer_Diff($g_aTimer[$i1][$TMR_STAMP]) / ($g_aTimer[$i1][$TMR_TIME] * 1000) * 100
If $nDiff > 100 Then
$nDiff = 100
$g_aTimer[$i1][$TMR_STATE] = False
EndIf
GUICtrlSetData($g_aTimer[$i1][$TMR_PROGR], $nDiff)
Next
EndFunc
Related
I have a thousands mini tools, I am trying to create a menu by using Autuit. I have to define thousand functions and case and variable how i can make it easy.
here is my code how can use loop for select case and run soft.exe
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
$Form1 = GUICreate("MainMenu", 615, 437, 192, 124)
$Soft1 = GUICtrlCreateButton("Button1", -8, 0, 75, 25)
$Soft2 = GUICtrlCreateButton("Button2", -18, 10, 75, 25)
$Soft3 = GUICtrlCreateButton("Button3", -28, 20, 75, 25)
$Soft4 = GUICtrlCreateButton("Button4", -38, 30, 75, 25)
$Soft5 = GUICtrlCreateButton("Button5", -48, 40, 75, 25)
$Soft6 = GUICtrlCreateButton("Button6", -58, 50, 75, 25)
GUISetState(#SW_SHOW)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $Soft1
Startsoft1()
Case $Soft2
Startsoft2()
Case $Soft3
Startsoft3()
Case $Soft4
Startsoft4()
Case $Soft5
Startsoft5()
Case $Soft6
Startsoft6()
EndSwitch
WEnd
Func Startsoft1()
Run('Soft1.exe')
EndFunc
Func Startsoft2()
Run('Soft2.exe')
EndFunc
Func Startsoft3()
Run('Soft3.exe')
EndFunc
Func Startsoft4()
Run('Soft4.exe')
EndFunc
Func Startsoft5()
Run('Soft5.exe')
EndFunc
iam new in programing there for learning new things
Try something like this as a good starting point.
Put the names and pathes in the strings of the method StringSplit.
The GUI buttons are automatically placed in a new line if the button reaches the GUI width end.
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
main()
Func main()
Local $gui_width = #DesktopWidth -100, $gui_height = #DesktopHeight - 80
Local $Form1 = GUICreate("MainMenu", $gui_width, $gui_height, 50, 10)
Local $exesName_A = StringSplit('a.exe,b.exe,c.exe,d.exe,e.exe,f.exe,g.exe,h.exe,i.exe,j.exe,k.exe,l.exe,m.exe,n.exe,o.exe,a.exe,b.exe,c.exe,d.exe,e.exe,f.exe,g.exe,h.exe,i.exe,j.exe,k.exe,l.exe,m.exe,n.exe,o.exe', ',', 2)
Local $exesPath_A = StringSplit('a.exe,b.exe,c.exe,d.exe,e.exe,f.exe,g.exe,h.exe,i.exe,j.exe,k.exe,l.exe,m.exe,n.exe,o.exe,a.exe,b.exe,c.exe,d.exe,e.exe,f.exe,g.exe,h.exe,i.exe,j.exe,k.exe,l.exe,m.exe,n.exe,o.exe', ',', 2)
Local $height = 45, $width = 125, $y = 0, $x = 0
Local $button_A[UBound($exesName_A)]
For $i = 0 To UBound($exesName_A) - 1
If ((8 + ($x + 1) * $width) > $gui_width) Then
$y += 1
$x = 0
EndIf
$button_A[$i] = GUICtrlCreateButton($exesName_A[$i], 8 + $x * $width, 10 + $y * $height, 75, $height)
GUICtrlSetImage(-1, "shell32.dll", 22+ $i)
$x += 1
Next
GUISetState(#SW_SHOW)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
; scan all buttons to check if one was pressed
For $i = 0 To UBound($button_A) - 1
If $nMsg = $button_A[$i] Then
ConsoleWrite('Now run the exe' & $exesPath_A[$i] & #CRLF)
;~ ShellExecute($exesPath_A[$i], '') ; uncomment this to run the exe
EndIf
Next
WEnd
EndFunc ;==>main
How to get an alert once on a supertrend trend,I think with while i can solve(but my knowledge is not enough),maybe is another way to solve my problem.
I need to skip the first signal(on down/up trend) and enter the second alert, and this signal alert one time per supertrend trend.
I describe signals below in the code.
//#version=5
indicator("My-Supertrend", overlay=true, timeframe="", timeframe_gaps=true)
atrPeriod = input(13, "ATR Length")
atrPeriod2 = input(21, "ATR Length2")
factor = input.float(3.0, "Factor", step = 0.01)
factor2 = input.float(7.0, "Factor2", step = 0.01)
[supertrend, direction] = ta.supertrend(factor, atrPeriod)
[supertrend2, direction2] = ta.supertrend(factor2, atrPeriod2)
//ST 1
bodyMiddle = plot((open + close) / 2, display=display.none)
upTrend = plot(direction < 0 ? supertrend : na, "Up Trend", color = #00cf42, style=plot.style_linebr,linewidth=1)
downTrend = plot(direction < 0? na : supertrend, "Down Trend", color = #bb2c01, style=plot.style_linebr,linewidth=1)
//ST 2
bodyMiddle2 = plot((open + close) / 2, display=display.none)
upTrend2 = plot(direction2 < 0 ? supertrend2 : na, "Up Trend", color = #00cf42, style=plot.style_linebr,linewidth=3)
downTrend2 = plot(direction2 < 0? na : supertrend2, "Down Trend", color = #bb2c01, style=plot.style_linebr,linewidth=3)
//ST1 color
fill(bodyMiddle, upTrend, color.new(#95bd06, 80), fillgaps=false)
fill(bodyMiddle, downTrend, color.new(#0692bd, 80), fillgaps=false)
//ST2 color
fill(bodyMiddle2, upTrend2, color.new(#5abd13, 70), fillgaps=false)
fill(bodyMiddle2, downTrend2, color.new(#bd3006,70), fillgaps=false)
//Logic
down_upTrend=direction>0 and direction2<0 and direction[1]<0
up_upTrend=direction<0 and direction2<0 and direction[1]>0
up_downTrend=direction<0 and direction2>0 and direction[1]>0
down_downTrend=direction>0 and direction2>0 and direction[1]<0
//For short
while direction2>0
up_downTrend
continue
down_downTrend
break
//For Long
while direction2<0
down_upTrend
continue
up_upTrend
break
plotshape(up_upTrend,style=shape.triangleup,location=location.belowbar,size=size.normal,color=color.rgb(27, 182, 27))
plotshape(up_downTrend,style=shape.triangleup,location=location.belowbar,size=size.normal,color=color.rgb(20, 112, 20))
plotshape(down_upTrend,style=shape.triangledown,location=location.abovebar,size=size.normal,color=color.rgb(255, 0, 0))
plotshape(down_downTrend,style=shape.triangledown,location=location.abovebar,size=size.normal,color=color.rgb(141, 21, 21))
alertcondition(up_upTrend or down_downTrend,"Long/Short","Signal")
I try to solve with while loop(and i describe my logic in while loop),but while dont work like I think.
I'm having to build a program which calculates the Annual cost of minutes used for phone providers and it depends on different rates.
As an example one phone operator may have the following rates:
"rates": [
{"price": 15.5, "threshold": 150},
{"price": 12.3, "threshold": 100},
{"price": 8}
],
operators can have multiple tariffs with the last tariff always having no threshold.
so in the example above the first 150 minutes will be charged at 15.5p per minute, the next 100mins will be charged at 12.3p per minute and all subsequent minutes will be charged at 8p.
Therefore if:
AnnualUsage = 1000
the total cost would be 95.55.
I'm struggling to visualise a method which would accommodate for the multiple tariffs an operator could have and multiplying a value by a different price depending on threshold.
Please Help!
Just another option, I think it's self explanatory:
rates = [
{price: 15.5, threshold: 150},
{price: 12.3, threshold: 100},
{price: 8}
]
annual_usage = 1000
res = rates.each_with_object([]) do |h, ary|
if h.has_key?(:threshold) && annual_usage > h[:threshold]
annual_usage -= h[:threshold]
ary << h[:threshold] * h[:price]/100
else
ary << annual_usage * h[:price]/100
end
end
res #=> [23.25, 12.3, 60]
res.sum #=> 95.55
Take a look to Enumerable#each_with_object.
def tot_cost(rate_tbl, minutes)
rate_tbl.reduce(0) do |tot,h|
mins = [minutes, h[:threshold] || Float::INFINITY].min
minutes -= mins
tot + h[:price] * mins
end
end
rate_tbl = [
{ price: 15.5, threshold: 150},
{ price: 12.3, threshold: 100 },
{ price: 8 }
]
tot_cost(rate_tbl, 130) #=> 2015.0 (130*15.5)
tot_cost(rate_tbl, 225) #=> 3247.5 (150*15.5 + (225-150)*12.3)
tot_cost(rate_tbl, 300) #=> 3955.0 (150*15.5 + 100*12.3 + (300-250)*8)
If desired, h[:threshold] || Float::INFINITY can be replaced by
h.fetch(:threshold, Float::INFINITY)
RATES = [
{price: 15.5, threshold: 150},
{price: 12.3, threshold: 100},
{price: 8}
]
def total_cost(annual_usage)
rate_idx = 0
idx_in_threshold = 1
1.upto(annual_usage).reduce(0) do |memo, i|
threshold = RATES[rate_idx][:threshold]
if threshold && (idx_in_threshold > RATES[rate_idx][:threshold])
idx_in_threshold = 1
rate_idx += 1
end
idx_in_threshold += 1
memo + RATES[rate_idx][:price]
end
end
puts total_cost(1000).to_i
# => 9555
The key concepts:
using an enumerable method such as reduce to incrementally build the solution. You could alternatively use each but reduce is more idiomatic.
tracking progress through the rates list through the rate_idx and idx_in_threshold variables. These give you all the information you need to determine whether you should advance to the next tier.
Also, avoid writing your hash keys like "price": 15.5 - just remove the quotations, it's more idiomatic.
With object-oriented approach you can remove explicit if ..else statements and maybe make code more self explanatory.
class Total
attr_reader :price
def initialize(usage)
#usage = usage
#billed_usage = 0
#price = 0
end
def apply(rate)
applicable_usage = [#usage - #billed_usage, 0].max
usage_to_apply = [applicable_usage, rate.fetch(:threshold, applicable_usage)].min
#price += usage_to_apply * rate[:price]
#billed_usage += usage_to_apply
end
end
Simple usage with each method
rates = [
{:price => 15.5, :threshold => 150},
{:price => 12.3, :threshold => 100},
{:price => 8}
]
total = Total.new(1000)
rates.each { |rate| total.apply(rate) }
puts "Total: #{total.price}" # Total: 9555.0 (95.55)
#include <GUIConstantsEx.au3>
#Include <GuiComboBox.au3>
#include <GuiComboBoxEx.au3>
; Create GUI
$hGUI = GUICreate("Test", 500, 500)
Global $hCombo = GUICtrlCreateCombo("", 10, 10, 250, 20)
GUICtrlSetData($hCombo, "Atchu | Muthu | Ponreegan | Vijay | Vasu", "Vasu")
$hGetButton = GUICtrlCreateButton("Get", 270, 10, 30, 20)
Global $temp = " "
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $hAddButton
$temp = _GUICtrlComboBoxEx_GetEditText($hCombo)
MsgBox($MB_SYSTEMMODAL, "", "You chose: " & $temp)
Exit
EndSwitch
WEnd
There are few names added to combo box, on clicking "Get button", it is not returning string. Any idea?
Your code does not even run. There are two issues:
The first is that you use $hGetButton when creating the button, but $hAddButton when waiting for a GUI message in your loop. This is what causes your code to fail to run.
The second issue is that you are using the wrong function to read the combobox data. You should use GUICtrlRead
Fixing these issues makes the code work:
#include <GUIConstantsEx.au3>
#Include <GuiComboBox.au3>
#include <GuiComboBoxEx.au3>
; Create GUI
$hGUI = GUICreate("Test", 500, 500)
Global $hCombo = GUICtrlCreateCombo("", 10, 10, 250, 20)
GUICtrlSetData($hCombo, "Atchu | Muthu | Ponreegan | Vijay | Vasu", "Vasu")
$hGetButton = GUICtrlCreateButton("Get", 270, 10, 30, 20)
Global $temp = " "
GUISetState ( #SW_SHOW , $hGUI )
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $hGetButton
$temp = GUICtrlRead($hCombo)
MsgBox($MB_SYSTEMMODAL, "", "You chose: " & $temp)
Exit
EndSwitch
WEnd
After searching on the internet, I know how to create a 1*j struct array. For example,
>> patient(1).name = 'John Doe';
patient(1).billing = 127.00;
patient(1).test = [79, 75, 73; 180, 178, 177.5; 220, 210, 205];
>>
>> patient(2).name = 'Ann Lane';
patient(2).billing = 28.50;
patient(2).test = [68, 70, 68; 118, 118, 119; 172, 170, 169];
My question is: how to create a j*1 struct array? Thanks so much for your time and attention.
There are two solutions:
You transpose your structure array afterwards:
patient = patient';
You index your structure array with two integers (first=row, second=column):
patient(j,1).name = 'John Doe';
Best,