ahk Considerations
By default
A.throwExceptions := true Wherever type errors can be detected, biga will throw an exception pointing out the location the error occurred. Set this to
false if you would like your script to continue without being stopped by biga.ahk
By default
A.limit := -1 Wherever possible biga.ahk will refer to this concerning limiting actions not specified by method arguments. Set this to
1 to get closer to the javascript experience. Currently only used by
.replace ie should
A.replace("aaaaaa", "a", "b") return "bbbbbb", "baaaaa", or something in between?
Examples
In the following example, we take on the role of a blogger, who wants to automate some features of their blog
Code: Select all
SetBatchLines -1
#NoTrayIcon
#SingleInstance force
#Include %A_ScriptDir%\node_modules
#Include biga.ahk\export.ahk
A := new biga()
blogPost := "This recipe is for a really scrumptious soup from Thailand. Grab a big bunch of lemongrass. We also need tomatoes."
; let's start by finding some interesting tags for this post. Breakup this post into an array of words and remove any duplicates
allWords := A.words(blogPost)
uniqWords := A.uniq(allWords)
; short words aren't useful for post tags. Let's remove anything that isn't at least 8 characters long
tagShortList := A.filter(uniqWords, Func("filterlengthFunc"))
filterlengthFunc(o) {
global
; We use A.size to measure the length of the string. But it can measure objects too
; StrLen would also work fine here and remove the need for global scope in this function
if (A.size(o) >= 8) {
return true
}
}
; the blog software wants all tags lowercase and in one long string separated by ","
lowercaseTags := A.map(tagShortList, A.toLower)
tags := A.join(lowercaseTags, ",")
; => "scrumptious,thailand,lemongrass,tomatoes"
; Let's pretend this blogpost was a lot longer and we only want {{3}} tags for this post. We can choose some tags at random from the larger collection
lessTags := A.sampleSize(lowercaseTags, 3)
; For the main page let's make a preview of the blogpost. 40 characters ought to do
postPreview := A.truncate(blogPost, 40)
; actually I prefer 15 words. You can combine different methods together for more power.
; .split creates an array limited to 15 items and .join turns it back into a string
postPreview := A.join(A.split(blogPost," ",15)," ") " [...]"
; => This recipe is for a really scrumptious soup from Thailand. Grab a big bunch of [...]
ExitApp
In this example, let's take on the role of a gaming script that announces which enemy to attack
Code: Select all
SetBatchLines -1
#NoTrayIcon
#SingleInstance force
#Include %A_ScriptDir%\node_modules
#Include biga.ahk\export.ahk
A := new biga()
enemies := [{"name": "bear", "hp": 200, "armor": 20, "status": "exposed_wound"}
, {"name": "wolf", "hp": 100, "armor": 12}
, {"name": "crab", "hp": 150, "armor": 99, "magicweakness": true}]
; Let's sort the enemies by hp and announce the one with the lowest hp as a target
sortedEnemies := A.sortBy(enemies, "hp")
; sorting by hp will move the lowest hp object to index 1
target := sortedEnemies[1].name
newEnemy := {"name": "weakened bear", "hp": 10, "armor": 5}
; a new enemy has appeared after we sorted the array. Instead of resorting; let's practice searching for the correct spot to insert at
mappedHP := A.map(sortedEnemies, "hp")
insertIndex := A.sortedIndex(mappedHP, newEnemy.hp)
; => 1
sortedEnemies.InsertAt(insertIndex, newEnemy)
; Assume rogues get bonus damage to anything with a status of "exposed_{{x}}" let's filter the sorted array by those and call all of them out. In this case there is only 1
exposedTargets := A.filter(sortedEnemies, Func("filterexposedFunc"))
filterexposedFunc(o) {
global
; We use A.startsWith inside this function to check the status
return % A.startsWith(o.status, "exposed")
}
; We can format our message with StartCase which is a ittle like ahk's TitleCase
callOutMessage := " Everyone attack: " A.startCase(sortedEnemies[1].name) "`n Rogues attack: " A.startCase(exposedTargets[1].name)
; Search the array of monsters for the first instance of one with "magicweakness" = true
magicweaknessTarget := A.find(sortedEnemies,"magicweakness")
callOutMessage := "Mages attack: " magicweaknessTarget.name
ExitApp
For the last example let's administer some online comments.
Code: Select all
SetBatchLines -1
#NoTrayIcon
#SingleInstance force
#Include %A_ScriptDir%\node_modules
#Include biga.ahk\export.ahk
A := new biga()
comments := [{"text": "I think...", "likes": 1, "sentiment": -9, "author": "Bob", "subscriber": false}
, {"text": "You see...", "likes": 2, "sentiment": 10, "author": "Fred", "subscriber": true}
, {"text": "Listen....", "likes": 9, "sentiment": 80, "author": "Barney", "subscriber": true}]
Newcomments := [{"text": "You see...", "likes": 2, "sentiment": 10, "author": "Fred", "subscriber": true}
, {"text": "You see...", "likes": 2, "sentiment": 10, "author": "Fred", "subscriber": true}]
; You can combine two arrays with .concat.
A.concat(comments, Newcomments)
; biga does NOT mutate inputs, changes are always delivered by the return value/object
comments := A.concat(comments, Newcomments)
; Theres a bug somewhere causing comments to be duplicated. In another example we used .uniq to remove duplicate strings, but it works on whole objects too.
comments := A.uniq(comments)
; Arrays can be reversed easily. Let's ensure that the negative comments are at the end of the array by sorting then reversing
negativeCommentsLast := A.reverse(A.sortBy(comments, "sentiment"))
; We can map the "sentiment" values to a new array for finding the average
sentimentArray := A.map(comments, "sentiment")
; => [-9, 10, 80]
; If you want to find out who is new in the comment section, how about mapping all the author names and finding the difference with regular posters
newFaces := A.difference(A.map(comments,"author"), ["Regular1","Regular2","Fred"])
; => ["Bob","Barney"]
; Let's choose a random subscriber comment to feature. Obviously we could filter by subscribers only and choose, but for the sake of example let's perform some logic
while (!featureComment) {
comment := A.sample(comments)
if (A.isMatch(comment, {"subscriber": true})) {
featureComment := comment
}
}
; Before injecting the comment into html, we can trim any leading and trailing whitespace
featureCommentText := A.trim(featureComment.text)
; let's trim any puncuation off the end as well
featureCommentText := A.trimEnd(featureCommentText, " .!?;:")
; .replace works like StrReplace but also accepts javascript formatted regular expressions. We'll remove any scripts the comment might have
featureCommentText := A.replace(featureCommentText, "/(<script>[\s\S]+<\/script>)/")
ExitApp