I need to switch sound sources using hotkeys. Scripts like this:
F6::
Run, mmsys.cpl
WinWait,Sound
ControlSend,SysListView321,{Down 2}
ControlClick,&Set Default
ControlClick,OK
return
F7::
Run, mmsys.cpl
WinWait,Sound
ControlSend,SysListView321,{Down 5}
ControlClick,&Set Default
ControlClick,OK
return
don't work. They just start 'sound devices' window
Requires a library VA:
F6::
loop
MsgBox % SwapAudioDevice("Speakers", "Digital Output")
SwapAudioDevice(device_A, device_B)
{
; Get device IDs.
A := VA_GetDevice(device_A), VA_IMMDevice_GetId(A, A_id)
B := VA_GetDevice(device_B), VA_IMMDevice_GetId(B, B_id)
if A && B
{
; Get ID of default playback device.
default := VA_GetDevice("playback")
VA_IMMDevice_GetId(default, default_id)
ObjRelease(default)
; If device A is default, set device B; otherwise set device A.
VA_SetDefaultEndpoint(default_id == A_id ? B : A, 0)
}
ObjRelease(B)
ObjRelease(A)
if !(A && B)
throw Exception("Unknown audio device", -1, A ? device_B : device_A)
Return default_id == A_id ? device_B : device_A
}
Return
Related
I am trying to solve a puzzle, and it has been suggested that I use backtracking - I did not know the term so did some investigation, and found the following in Wikipedia:
In order to apply backtracking to a specific class of problems, one must provide the data P for the particular instance of the problem that is to be solved, and six procedural parameters, root, reject, accept, first, next, and output. These procedures should take the instance data P as a parameter and should do the following:
root(P): return the partial candidate at the root of the search tree.
reject(P,c): return true only if the partial candidate c is not worth completing.
accept(P,c): return true if c is a solution of P, and false otherwise.
first(P,c): generate the first extension of candidate c.
next(P,s): generate the next alternative extension of a candidate, after the extension s.
output(P,c): use the solution c of P, as appropriate to the application.
The backtracking algorithm reduces the problem to the call backtrack(root(P)), where backtrack is the following recursive procedure:
procedure backtrack(c) is
if reject(P, c) then return
if accept(P, c) then output(P, c)
s ← first(P, c)
while s ≠ NULL do
backtrack(s)
s ← next(P, s)
I have attempted to use this method for my solution, but after the method finds a rejected candidate it just starts again and finds the same route, rather than the next possible one.
I now don't think I have used the next(P,s) correctly, because I don't really understand the wording 'after the extension s'.
I've tried 2 methods:
(a) in the first() function, generating all possible extensions, storing them in a list, then using the first. The next() function then uses the other extensions from the list in turn. But this maybe can't work because of the calls to backtrack() in between the calls to next().
(b) adding a counter to the data (i.e. the class that includes all the grid info) and incrementing this for each call of next(). But can't work out where to reset this counter to zero.
Here's the relevant bit of code for method (a):
private PotentialSolution tryFirstTrack(PotentialSolution ps)
{
possibleTracks = new List<PotentialSolution>();
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(ps);
}
}
return tryNextTrack(ps);
}
private PotentialSolution tryNextTrack(PotentialSolution ps)
{
if (possibleTracks.Count == 0)
{
ps.SetCell(Track.Empty);
return null;
}
ps = possibleTracks.First();
// don't use same one again
possibleTracks.Remove(ps);
return ps;
}
private bool backtrackTracks(PotentialSolution ps)
{
if (canExit)
{
return true;
}
if (checkOccupiedCells(ps))
{
ps = tryFirstTrack(ps);
while (ps != null)
{
// 'testCells' is a copy of the grid for use with graphics - no need to include graphics in the backtrack stack
testCells[ps.h, ps.w].DrawTrack(g, ps.GetCell());
if (ps.TestForExit(endColumn, ref canExit) != Track.MaxVal)
{
drawRowColTotals(ps);
return true;
}
ps.nextSide = findNextSide(ps.nextSide, ps.GetCell(), ref ps.h, ref ps.w);
if (ps.h >= 0 && ps.h < cellsPerSide && ps.w >= 0 && ps.w < cellsPerSide)
{
backtrackTracks(ps);
ps = tryNextTrack(ps);
}
else
return false;
}
return false;
}
return false;
}
and here's some code using random choices. This works fine, so I conclude that the methods checkOccupiedCells() and findNextSide() are working correctly.
private bool backtrackTracks(PotentialSolution ps)
{
if (canExit)
{
return true;
}
if (checkOccupiedCells(ps))
{
Track track = createRandomTrack(ps);
if (canExit)
return true;
if (track == Track.MaxVal)
return false;
ps.SetCell(track);
ps.nextSide = findNextSide(ps.nextSide, track, ref ps.h, ref ps.w);
if (ps.h >= 0 && ps.h < cellsPerSide && ps.w >= 0 && ps.w < cellsPerSide)
backtrackTracks(ps);
else
return false;
}
}
If it helps, there's more background info in the puzzle itself here
Consider the following rule for "locations" r and s:
∀r,s[(danger(r)∧adjacent(r,s))→danger(s)]
I tried to implement as follows:
function boolean adjacent(Location l1, Location l2) {
if (l1.x == l2.x)
return Math.abs(l1.y - l2.y) == 1;
if (l1.y == l2.y)
return Math.abs(l1.x - l2.x) == 1;
return false;
}
rule danger
when
$s : Location(danger == true)
$r : Location()
adjacent($s,$r)
then
modify($r) { setDanger(true) }
end;
But it does not compile saying that adjacent cannot be resolved.
I tried eval(adjacent($s,$r)) but it does not work because rete keeps visiting the same combinations of $s and $r forever.
I tried implementing adjacent() method on Location, but it does not compile either:
$r : Location(adjacent($s) == true)
I thought on some alternatives like: making each Location has a list of adjacent locations; etc. But none of them sounded right for me.
How would be the right way to implement this?
rule danger
when
$s : Location( danger )
$r : Location(! danger, adjacent($s,$r) )
then
modify($r) { setDanger(true) }
end
You can write a boolean expression as a constraint, or inside an eval CE (but never as a pattern all by itself, as you tried).
To avoid the loop, add a constraint that fails after the modify.
I have created a vending machine it works fine. I want to subtract 1 from the quantity of items once the transaction is completed. I have provided comments in my code for understanding. Ignore some of the comments in pred chocolate. Somehow I am trying to subtract but it just wont. I don't know what seems to be the problem. Any help is appreciated .
sig button {
qty:Int} // buttons on vending machine for selecting chocolates
//sig coin{}
sig choco{
value:Int, // Each chocolate has some cost as an attribute aka value.
choice :one button // Selecting option
}
fact {
// all c:choco | all c1:choco -c | c1.choice != c.choice
}
sig machine{
cust : one customer, // Customer entity
a,b,c,d,nullb ,ip: one button, // buttons on vending machine ,ip is the input selected by user
//oners,twors,fivers ,tenrs,null1: set coin,
ipp,opc2 : one Coin, // ipp = input rs , opc = balance rs
customeripb: cust one -> one ip, // customer presses a button
customeripc: cust one -> one ipp, // customer enters coins
customeropc: opc2 one -> one cust, //customer receives balance of coins
op: one choco , // output of chocolate from machine
customerop: op one -> one cust, // customer receives a chocolate
cadbury, kitkat, eclairs , gum,null: lone choco // types of chocolate
}
{
//#(fivers+tenrs+null+twors+oners) = 5
#(a+b+c+d) = 4 // no of buttons of a b c and d are 4 on machine
# (cadbury+kitkat+ eclairs +gum) =4 // no of options to choose = 4
cadbury=choice.a // cadbury corresponds to button a
cadbury.value= 10 // cadbury costs 10rs
kitkat=choice.b // kitkat corresponds to button b
kitkat.value=5 // kitkat costs 5rs
null.value=0 // null costs 0 rs
null=choice.nullb
// as such null doesnt exist it is just to specify no i/p no o/p and nulb is an imaginary button
eclairs=choice.c // eclairs corresponds to button c
eclairs.value=1 // eclairs costs 1 rs
gum=choice.d // gum corresponds to button d
gum.value=2 // gum costs 1 rs
a.qty>=10 and a.qty<=40
b.qty>=11 and b.qty<=40
c.qty>=12 and c.qty<=40
d.qty>=13 and d.qty<=40
nullb.qty=0
//ip=nullb //input button selection is never nullb(which is imaginary button)
ipp.value!=0 // input of coins is never = 0rs
/* all m:machine|all o:opc2
|all opp: op| all i:ip|all ii:ipp| all c:m.cust
|c -> i in m.customeripb and c->ii in m.customeripc and o->c in m.customerop and opp->c in m.customerop
*/
//button=!=none
}
sig customer //user of machine
{
}
abstract sig Coin { //each coin has a valueof rs
value: Int
}
sig Nullrs extends Coin {} { value = 0 } // void rs
sig Oners extends Coin {} { value = 1 } // one rs
sig Twors extends Coin {} { value = 2 } // twors
sig Fivers extends Coin {}{ value = 5 } // five rs
sig Tenrs extends Coin {} { value = 10 } // ten rs
sig Threers extends Coin {} { value = 3 } // this is only used in o/p to specify 3rs will come out
sig Fourrs extends Coin {} { value = 4 }// this is only used in o/p to specify 4rs will come out
sig Sixrs extends Coin {} { value = 6 }// this is only used in o/p to specify 6rs will come out
sig Sevenrs extends Coin {}{ value = 7 }// this is only used in o/p to specify 7rs will come out
sig Eightrs extends Coin {} { value = 8 } // this is only used in o/p to specify 8rs will come out
sig Niners extends Coin {} { value = 9} //// this is only used in o/p to specify 9rs will come out
pred show{} // show
pred chocolate [before,after:machine ] // machine has two states one before o/p and one after
{
before.cadbury=after.cadbury
before.kitkat=after.kitkat
before.eclairs=after.eclairs
before.gum=after.gum
//all chocolates will not change and are fixed
before.ipp.value=after.ipp.value
// input value of rs remains same i.e i/p is inside machine once inputed so it cant change
before.opc2.value=0 // before state o/p value of balance coins =0
before.op=before.null // beforestate o/p = no chocolate
before.ip!=before.nullb // input button pressed never equals nullb
after.ip!=after.nullb // input button pressed never equals nullb
//before.ip=after.ip // input button pressed remains same
after.op=after.kitkat or after.op=after.eclairs
before.null=after.null // imaginary null chocolate remains in same state
before.opc2!=none and after.opc2 !=none
// balance of coins is never empty in case of empty I have defined nullrs
(after.op.value=before.ipp.value=>after.opc2.value=0)
//
(after.op=after.null=>after.opc2.value=before.ipp.value)
(before.ipp.value > after.op.value=>after.opc2.value=before.ipp.value-after.op.value)
//(before.ipp.value=after.op.value=>after.opc2.value=0)
//opc2.value!=ipp.value
before.ip=before.a or before.ip=before.b or before.ip=before.c or before.ip=before.d
(after.op=after.cadbury ) => ( ( after.ip=after.a and after.a.qty=minus[before.a.qty,1])) else
(after.op=after.kitkat ) => ( (after.ip=after.b and after.b.qty=minus[before.b.qty, 1])) else
(after.op=after.eclairs ) =>( (after.ip=after.c and after.c.qty=minus[before.c.qty,1])) else
(after.op=after.gum ) =>((after.ip=after.d and after.d.qty=minus[before.d.qty,1])) else
(after.ip=before.ip and after.ip.qty=minus[before.ip.qty,0] )
after.op!=before.null => after.op.choice=before.ip
(after.op=before.gum=>before.ipp.value>=Twors.value)
after.op=before.cadbury=>before.ipp.value>=Tenrs.value
after.op=before.eclairs=>before.ipp.value>=Oners.value
after.op=before.kitkat=>before.ipp.value>=Fivers.value
(before.ipp=Oners or before.ipp=Twors or before.ipp=Fivers or before.ipp=Tenrs or before.ipp=Nullrs) and
before.ipp!=Threers and before.ipp!=Fourrs and before.ipp !=Sixrs and before.ipp!=Sevenrs and before.ipp!=Eightrs and before.ipp!=Niners
(before.ip=before.b and before.ipp.value < 5) => (after.op!=before.kitkat or after.op!=before.eclairs or after.op!=before.cadbury or after.op!=before.gum)and after.op=before.null
(before.ip=before.d and before.ipp.value < 2) => (after.op!=before.kitkat or after.op!=before.eclairs or after.op!=before.cadbury or after.op!=before.gum)and after.op=before.null
(before.ip=before.a and before.ipp.value < 10 )=> (after.op!=before.kitkat or after.op!=before.eclairs or after.op!=before.cadbury or after.op!=before.gum) and after.op=before.null
(before.ip=before.c and before.ipp.value >= 1) => (after.op!=before.kitkat or after.op!=before.null or after.op!=before.cadbury or after.op!=before.gum) and after.op=before.eclairs
(before.ip=before.c and before.ipp.value = 0) => (after.op!=before.kitkat or after.op!=before.null or after.op!=before.cadbury or after.op!=before.gum) and after.op=before.null
(before.ip=before.a and before.ipp.value =10) => (after.op!=before.kitkat or after.op!=before.null or after.op!=before.eclairs or after.op!=before.gum) and after.op= before.cadbury
(before.ip=before.d and before.ipp.value >= 2) => (after.op!=before.kitkat or after.op!=before.null or after.op!=before.cadbury or after.op!=before.eclairs) and after.op=before.gum
(before.ip=before.b and before.ipp.value >= 5) => (after.op!=before.eclairs or after.op!=before.null or after.op!=before.cadbury or after.op!=before.gum) and after.op=before.kitkat
}
run chocolate for exactly 2 machine, 8 button, 5 choco,9 Int,5 Coin,1 customer
In general, it would make sense to be more specific than "it doesn't work".
I'm assuming that what you mean by "it doesn't work" is that in the after machine you expect the quantity of the selected chocolate to be decreased by 1, but instead, it stays the same. The reason for that is your (if-then-else) or (if-then-else) or ... expression, which is logically flawed. What you probably wanted to express is to enforce at least one then branch (because you know that exactly one if condition will be satisfied), but that is not necessary to satisfy this whole disjunction.
More concretely, in
((after.op=after.cadbury)
=> (... and after.a.qty=minus[before.a.qty,1] and ...)
else (... and after.a.qty=before.a.qty and ...)
)
or
((after.op=after.kitkat)
=> (... and after.b.qty=minus[before.b.qty,1] and ...)
else (... and after.b.qty=before.b.qty and ...)
)
even if after.op is equal to after.cadbury, that does not enforce the then branch of that clause to be true, because to satisfy this whole expression, it is enough to satisfy the else branch of the next clause, which says that all quantities should stay the same.
What you want is some soft of if-then-elsif-...-else construct, e.g.,
(after.op = after.cadbury) => {
...
} else (after.op = after.kitkat) => {
...
} else {
...
}
If you do that, your machine will still not work, that is, your model will become unsatisfiable: your constraints enforce that both after and before machines share the same buttons1 and quantities are associated with buttons (the qty field is in the button sig), which means that quantities must be the same in both after and before machines. I don't really see any good reason to put qty in sig button.
[1]: by having before.cadbury=after.cadbury and ... in your chocolate predicate, and cadbury=choice.a and ... in your appended facts for sig machine
My Code is below.Whenever I try to run it I get an error saying I'm using duplicate hotkeys when in practice they would never interfere with each other. How do I get around this?
"Your post does not have much context to explain the code sections; please explain your scenario more clearly.". So I guess need to explain my code.. It's extremely simple I have a state variable that is changed by pressing the arrow keys, then I have if statements that checks what the state is. If I press numpad1 when state = "up" the script should type "A", if the state = "right" it would print I. However I'm getting an error since I used the same hotkey multiple times in my different if statements.
state := "none"
UP::
state := "up"
Right::
state := "right"
DOWN::
state := "down"
LEFT::
state := "left"
if (state = "up"){
Numpad1::
Send A
Return
Numpad2::
Send B
Return
Numpad3::
Send C
Return
Numpad4::
Send D
Return
Numpad6::
Send E
Return
Numpad7::
Send F
Return
Numpad8::
Send G
Return
Numpad9::
Send H
Return
}
if (sate = "right"){
Numpad1::
Send I
Return
Numpad2::
Send J
Return
Numpad3::
Send K
Return
Numpad4::
Send L
Return
Numpad6::
Send M
Return
Numpad7::
Send N
Return
Numpad8::
Send O
Return
Numpad9::
Send P
Return
}
if (state = "down"){
Numpad1::
Send Q
Return
Numpad2::
Send R
Return
Numpad3::
Send S
Return
Numpad4::
Send T
Return
Numpad6::
Send U
Return
Numpad7::
Send V
Return
Numpad8::
Send W
Return
Numpad9::
Send X
Return
}
if (state = "left"){
Numpad1::
Send Y
Return
Numpad2::
Send Z
Return
}
When you use AHK_L, you can use #IF with multiple definitions of the same hotkey. WARNING this does NOT work with the regular AHK version.
Here is an example.
You set the variables by typing none\ right\ or left\ .
Depending on the variable setting your Tab key will either send NORMAL, LEFT or RIGHT.
#SingleInstance Force
Tab::Send, NORMAL
#if (state = "left")
Tab::Send, LEFT
#if ; End #if (state = "left")
#if (state = "right")
Tab::Send, RIGHT
#if ; End #if (state = "right")
:*:right\::
state := "right"
Return
:*:left\::
state := "left"
Return
:*:none\::
state := "none"
Return
Alternatively, with the normal AHK, you define ONE hotkey and place IF statements inside the hotkeys to change the behaviour based on the state variable.
I thought even after rendering the page, removing script tags and the relevant attributes in tags would work but didn't.
The following code removes the script tag and the onclick attribute but it does not have any effect.
Any idea?
I'd like to avoid:
editing the registroy since it requires admin rights.
fetching web contents separately and using doc.write() since it make the code complex.
Files:
javascript.html
test.ahk
javascript.html
<!DOCTYPE html>
<html>
<head>
<script> function displayDate() { document.getElementById("demo").innerHTML=Date(); }</script>
</head>
<body>
<p id="demo" onclick="displayDate()">This is a paragraph. Click here.</p>
</body>
</html>
test.ahk
Gui, Add, ActiveX, vWB w400 h300, Shell.Explorer
Gui, Show, w420 h320
WB.Navigate("file:///" A_ScriptDir "/javascript.html")
Loop
Sleep 10
Until (WB.readyState=4 && WB.document.readyState="complete" && !WB.busy)
doc := WB.document
nodeScript := doc.getElementsByTagName("script")[0]
nodeScript.parentNode.removeChild(nodeScript)
nodeP := doc.getElementsByTagName("p")[0]
nodeP.removeAttribute("onclick")
msgbox % doc.documentElement.outerHTML
Return
It is possible to force scripting enabled/disabled for a given WebBrowser control by implementing three specific COM interfaces (IOleClientSite, IServiceProvider and IInternetSecurityManager) and calling the SetClientSite method of the control's IOleObject interface.
Ultimately, you need to implement the IInternetSecurityManager::ProcessUrlAction method. When the WebBrowser calls it with the dwAction parameter set to URLACTION_SCRIPT_RUN, you can set *pPolicy to URLPOLICY_DISALLOW to prevent scripting or URLPOLICY_ALLOW to enable scripting, and return S_OK (zero) to enforce the policy.
The necessary code is shown below, and can be implemented by simply calling SetWBClientSite() after creating the control but before navigating. The global variable WB must contain a reference to the WebBrowser control.
/* Complex workaround to override "Active scripting" setting
* and ensure scripts can't run within the WebBrowser control.
*/
global WBClientSite
SetWBClientSite()
{
interfaces := {
(Join,
IOleClientSite: [0,3,1,0,1,0]
IServiceProvider: [3]
IInternetSecurityManager: [1,1,3,4,8,7,3,3]
)}
unkQI := RegisterCallback("WBClientSite_QI", "Fast")
unkAddRef := RegisterCallback("WBClientSite_AddRef", "Fast")
unkRelease := RegisterCallback("WBClientSite_Release", "Fast")
WBClientSite := {_buffers: bufs := {}}, bufn := 0,
for name, prms in interfaces
{
bufn += 1
bufs.SetCapacity(bufn, (4 + prms.MaxIndex()) * A_PtrSize)
buf := bufs.GetAddress(bufn)
NumPut(unkQI, buf + 1*A_PtrSize)
NumPut(unkAddRef, buf + 2*A_PtrSize)
NumPut(unkRelease, buf + 3*A_PtrSize)
for i, prmc in prms
NumPut(RegisterCallback("WBClientSite_" name, "Fast", prmc+1, i), buf + (3+i)*A_PtrSize)
NumPut(buf + A_PtrSize, buf + 0)
WBClientSite[name] := buf
}
global wb
if pOleObject := ComObjQuery(wb, "{00000112-0000-0000-C000-000000000046}")
{ ; IOleObject::SetClientSite
DllCall(NumGet(NumGet(pOleObject+0)+3*A_PtrSize), "ptr"
, pOleObject, "ptr", WBClientSite.IOleClientSite, "uint")
ObjRelease(pOleObject)
}
}
WBClientSite_QI(p, piid, ppvObject)
{
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
static IID_IOleClientSite := "{00000118-0000-0000-C000-000000000046}"
static IID_IServiceProvider := "{6d5140c1-7436-11ce-8034-00aa006009fa}"
iid := _String4GUID(piid)
if (iid = IID_IOleClientSite || iid = IID_IUnknown)
{
NumPut(WBClientSite.IOleClientSite, ppvObject+0)
return 0 ; S_OK
}
if (iid = IID_IServiceProvider)
{
NumPut(WBClientSite.IServiceProvider, ppvObject+0)
return 0 ; S_OK
}
NumPut(0, ppvObject+0)
return 0x80004002 ; E_NOINTERFACE
}
WBClientSite_AddRef(p)
{
return 1
}
WBClientSite_Release(p)
{
return 1
}
WBClientSite_IOleClientSite(p, p1="", p2="", p3="")
{
if (A_EventInfo = 3) ; GetContainer
{
NumPut(0, p1+0) ; *ppContainer := NULL
return 0x80004002 ; E_NOINTERFACE
}
return 0x80004001 ; E_NOTIMPL
}
WBClientSite_IServiceProvider(p, pguidService, piid, ppvObject)
{
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
static IID_IInternetSecurityManager := "{79eac9ee-baf9-11ce-8c82-00aa004ba90b}"
if (_String4GUID(pguidService) = IID_IInternetSecurityManager)
{
iid := _String4GUID(piid)
if (iid = IID_IInternetSecurityManager || iid = IID_IUnknown)
{
NumPut(WBClientSite.IInternetSecurityManager, ppvObject+0)
return 0 ; S_OK
}
NumPut(0, ppvObject+0)
return 0x80004002 ; E_NOINTERFACE
}
NumPut(0, ppvObject+0)
return 0x80004001 ; E_NOTIMPL
}
WBClientSite_IInternetSecurityManager(p, p1="", p2="", p3="", p4="", p5="", p6="", p7="", p8="")
{
if (A_EventInfo = 5) ; ProcessUrlAction
{
if (p2 = 0x1400) ; dwAction = URLACTION_SCRIPT_RUN
{
NumPut((URLPOLICY_DISALLOW := 3), p3+0) ; *pPolicy := URLPOLICY_DISALLOW
return 0 ; S_OK
}
}
return 0x800C0011 ; INET_E_DEFAULT_ACTION
}
_String4GUID(pGUID)
{
VarSetCapacity(String,38*2)
DllCall("ole32\StringFromGUID2", "ptr", pGUID, "str", String, "int", 39)
Return String
}
The current AutoHotkey installer contains code identical to this, with the exception that it sets URLPOLICY_ALLOW (0) rather than URLPOLICY_DISALLOW (3). This was necessary to allow the installer to work on systems which have scripting disabled.
As you can see, implementing COM interfaces directly in an AutoHotkey script is no simple matter. It is a little easier in plain C (see COM in plain C), and much easier in C++.