diff --git a/README.md b/README.md index 88a4f50..71e9553 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@
  • option to display time when it chimes/strikes/toll ;-)
  • ... with an analog clock display (optional)
  • tick/tock background sound
  • -
  • display a Bible verse in English, French or Spanish, at a specified interval (e.g., every three hours)
  • +
  • display a random Bible verse in English, French or Spanish, at a specified interval (e.g., every three hours)
  • informs you about moon phases, equinoxes and solstices, and how much of the current day or year has elapsed
  • option to display / observe Christian feast days - for Orthodox and Catholic worshippers; automatically calculates the dates for Easter and related celebrations
  • options to set an alarm or a timer
  • diff --git a/bells-tower-change-log.txt b/bells-tower-change-log.txt index a499cc0..d232a1b 100644 --- a/bells-tower-change-log.txt +++ b/bells-tower-change-log.txt @@ -5,6 +5,13 @@ ; Work began on this project in late August 2018. ; ====================================================== +v3.1.7 - 2022 / 09 / 08 + - [new] option to display a progress bar in the OSD; users have the ability to choose from several time related progress bars + - [new] option to mark full moon by wolves howling [audio] + - improved the algorithm that calculates the moon phases; it is now a lot more accurate + - improved how the moon phases are drawn in the analog clock widget + - the dates for equinoxes and solstices are now calculated based on the current time zone + v3.1.6 - 2022 / 04 / 16 - small fixes; many thanks to Fantmp diff --git a/bells-tower.ahk b/bells-tower.ahk index 5944a73..31b3107 100644 --- a/bells-tower.ahk +++ b/bells-tower.ahk @@ -20,10 +20,10 @@ ; =========================================================== ; ;@Ahk2Exe-SetName Church Bells Tower -;@Ahk2Exe-SetCopyright Marius Şucan (2017-2018) +;@Ahk2Exe-SetCopyright Marius Şucan (2017-2022) ;@Ahk2Exe-SetCompanyName http://marius.sucan.ro ;@Ahk2Exe-SetDescription Church Bells Tower -;@Ahk2Exe-SetVersion 3.1.6 +;@Ahk2Exe-SetVersion 3.1.7 ;@Ahk2Exe-SetOrigFilename bells-tower.ahk ;@Ahk2Exe-SetMainIcon bells-tower.ico @@ -41,6 +41,7 @@ #Include, Lib\gdip_all.ahk #Include, Lib\analog-clock-display.ahk #Include, Lib\Class_CtlColors.ahk + #Include, Lib\Maths.ahk DetectHiddenWindows, On ComObjError(false) @@ -56,7 +57,7 @@ , LargeUIfontValue := 13 , uiDarkMode := 0 , tollQuarters := 1 - , tollQuartersException := 0 + , tollQuartersException:= 0 , tollHours := 1 , tollHoursAmount := 1 , tollNoon := 1 @@ -89,6 +90,7 @@ , NoWelcomePopupInfo := 0 , showTimeWhenIdle := 0 , showTimeIdleAfter := 5 ; [in minutes] + , markFullMoonHowls := 0 ; OSD settings Global displayTimeFormat := 1 @@ -98,6 +100,7 @@ Global displayTimeFormat := 1 , analogDisplayScale := 0.3 , analogMoonPhases := 1 , constantAnalogClock := 0 + , showOSDprogressBar := 2 , GuiX := 40 , GuiY := 250 , ClockGuiX := 40 @@ -146,14 +149,15 @@ Global displayTimeFormat := 1 , ClockWinSize := ClockDiameter + 2 , ClockCenter := Round(ClockWinSize/2) , roundedCsize := Round(ClockDiameter/4) + , EquiSolsCache := 0 ; Release info , ThisFile := A_ScriptName - , Version := "3.1.6" - , ReleaseDate := "2022 / 04 / 16" + , Version := "3.1.7" + , ReleaseDate := "2022 / 09 / 08" , storeSettingsREG := FileExist("win-store-mode.ini") && A_IsCompiled && InStr(A_ScriptFullPath, "WindowsApps") ? 1 : 0 , ScriptInitialized, FirstRun := 1 - , QuotesAlreadySeen := "", LastWinOpened + , QuotesAlreadySeen := "", LastWinOpened, hasHowledDay := 0 , LastNoonAudio := 0, appName := "Church Bells Tower" , APPregEntry := "HKEY_CURRENT_USER\SOFTWARE\" appName "\v1-1" @@ -199,12 +203,12 @@ Global CSthin := "░" ; light gray , lastFaded := 1 , cutVolumeHalf := 0 , defAnalogClockPosChanged := 0 - , FontChangedTimes := 0 - , AnyWindowOpen := 0 + , FontChangedTimes := 0, AnyWindowOpen := 0, CurrentPrefWindow := 0 + , mEquiDay := 79, jSolsDay := 172, sEquiDay := 266, dSolsDay := 356 + , mEquiDate := A_Year "0320010203", jSolsDaTe := A_Year "0621010203", sEquiDate := A_Year "0923010203", dSolsDaTe := A_Year "1222010203" , LastBibleQuoteDisplay := 1 , LastBibleQuoteDisplay2 := 1 , LastBibleMsg := "", AllowDarkModeForWindow := "" - , CurrentPrefWindow := 0 , celebYear := A_Year, userAlarmIsSnoozed := 0 , isHolidayToday := 0, stopWatchRecordsInterval := [] , TypeHolidayOccured := 0, userTimerExpire := 0 @@ -225,7 +229,7 @@ Global CSthin := "░" ; light gray , SNDmedia_auxil_bell, SNDmedia_japan_bell, SNDmedia_christmas , SNDmedia_evening, SNDmedia_midnight, SNDmedia_morning, SNDmedia_beep , SNDmedia_noon1, SNDmedia_noon2, SNDmedia_noon3, SNDmedia_noon4 - , SNDmedia_orthodox_chimes1, SNDmedia_orthodox_chimes2 + , SNDmedia_orthodox_chimes1, SNDmedia_orthodox_chimes2, SNDmedia_Howl , SNDmedia_semantron1, SNDmedia_semantron2, SNDmedia_hours12, SNDmedia_hours11 , SNDmedia_quarters1, SNDmedia_quarters2, SNDmedia_quarters3, SNDmedia_quarters4 , SNDmedia_hours1, SNDmedia_hours2, SNDmedia_hours3, SNDmedia_hours4, SNDmedia_hours5 @@ -303,6 +307,7 @@ InitSoundChannels() { SNDfile_noon2 := A_ScriptDir "\sounds\noon2.mp3" SNDfile_noon3 := A_ScriptDir "\sounds\noon3.mp3" SNDfile_noon4 := A_ScriptDir "\sounds\noon4.mp3" + SNDfile_howl := A_ScriptDir "\sounds\howling.mp3" SNDfile_chimes1 := A_ScriptDir "\sounds\orthodox-chimes1.mp3" SNDfile_chimes2 := A_ScriptDir "\sounds\orthodox-chimes2.mp3" SNDfile_quarters := A_ScriptDir "\sounds\quarters.mp3" @@ -329,21 +334,35 @@ InitSoundChannels() { SNDmedia_noon4 := MCI_Open(SNDfile_noon4) SNDmedia_orthodox_chimes1 := MCI_Open(SNDfile_chimes1) SNDmedia_orthodox_chimes2 := MCI_Open(SNDfile_chimes2) + SNDmedia_Howl := MCI_Open(SNDfile_howl) SNDmedia_semantron1 := MCI_Open(SNDfile_semantron1) SNDmedia_semantron2 := MCI_Open(SNDfile_semantron2) SNDmedia_ticktok := MCI_Open(SNDfile_ticktok) } TimerShowOSDidle() { - Static isThisIdle := 0 + Static isThisIdle := 0, lastFullMoonZeitTest := -9020 If (constantAnalogClock=1) || (analogDisplay=1 && ClockVisibility=1) || (PrefOpen=1) || (A_IsSuspended) Return If !A_IsSuspended mouseHidden := checkMcursorState() - If (showTimeWhenIdle=1 && (A_TimeIdle > userIdleAfter) && mouseHidden!=1) + If (showTimeWhenIdle=1 && (A_TimeIdle > userIdleAfter) && mouseHidden!=1) { + FormatTime, HoursIntervalTest,, H ; 0-23 format + If (markFullMoonHowls=1 && hasHowledDay!=A_YDay && userMuteAllSounds!=1 && lastFullMoonZeitTest!=HoursIntervalTest) + { + lastFullMoonZeitTest := HoursIntervalTest + pk := MoonPhaseCalculator() + If InStr(pk[1], "full moon (peak)") + { + hasHowledDay := A_YDay + INIaction(1, "hasHowledDay", "SavedSettings") + volumeAction := SetMyVolume() + MCXI_Play(SNDmedia_Howl) + } + } isThisIdle := 1 DoGuiFader := 0 If (BibleGuiVisible!=1) @@ -457,19 +476,15 @@ decideSysTrayTooltip() { thisHoli := "secular" thisHoli := (StrLen(isHolidayToday)>2) ? "`nToday a " thisHoli " event is observed" : "" - - testu := compareYearDays(78, A_YDay) ; 03 / 20 - If InStr(testu, "now") - resu := "`nSpring equinox" - testu := compareYearDays(170, A_YDay) ; 06 / 21 - If InStr(testu, "now") - resu := "`nSummer solstice" - testu := compareYearDays(263, A_YDay) ; 09 / 22 - If InStr(testu, "now") - resu := "`nAutumn equinox" - testu := compareYearDays(354, A_YDay) ; 12 / 21 - If InStr(testu, "now") - resu := "`nWinter solstice" + testu := wrapCalculateEquiSolsDates() + If (testu.r=1) + resu := "`nMarch equinox" + Else If (testu.r=2) + resu := "`nJune solstice" + Else If (testu.r=3) + resu := "`nSeptember equinox" + Else If (testu.r=4) + resu := "`nDecember solstice" Menu, Tray, Tip, % appName " v" Version RunType timerInfos alarmInfos stopwInfos thisHoli resu soundsInfos lastInvoked := A_TickCount @@ -999,7 +1014,8 @@ readjustBibleTimer() { theChimer() { Critical, on - Static lastChimed, todayTest + Static lastChimed, todayTest, lastFullMoonZeitTest := -9000 + FormatTime, CurrentTime,, hh:mm If (lastChimed=CurrentTime || A_IsSuspended || PrefOpen=1) mustEndNow := 1 @@ -1013,20 +1029,33 @@ theChimer() { mustEndNow := stopAdditionalStrikes := 1 } - If (todayTest!=A_MDay) && (ScriptInitialized=1) + If (noTollingWhenMhidden=1) + mouseHidden := checkMcursorState() + + If (todayTest!=A_YDay && ScriptInitialized=1) { Sleep, 10 testCelebrations() } - If (noTollingWhenMhidden=1) - mouseHidden := checkMcursorState() + If (markFullMoonHowls=1 && hasHowledDay!=A_YDay && mouseHidden!=1 && mustEndNow!=1 && userMuteAllSounds!=1 && lastFullMoonZeitTest!=HoursIntervalTest) + { + lastFullMoonZeitTest := HoursIntervalTest + pk := MoonPhaseCalculator() + If InStr(pk[1], "full moon (peak)") + { + hasHowledDay := A_YDay + INIaction(1, "hasHowledDay", "SavedSettings") + volumeAction := SetMyVolume() + MCXI_Play(SNDmedia_Howl) + } + } - todayTest := A_MDay - If (HoursIntervalTest>=silentHoursA && HoursIntervalTest<=silentHoursB && silentHours=2) + todayTest := A_YDay + If (isInRange(HoursIntervalTest, silentHoursA, silentHoursB) && silentHours=2) soundBells := 1 - If (HoursIntervalTest>=silentHoursA && HoursIntervalTest<=silentHoursB && silentHours=3) + If (isInRange(HoursIntervalTest, silentHoursA, silentHoursB) && silentHours=3) || (soundBells!=1 && silentHours=2) || (mustEndNow=1) || (mouseHidden=1) { If (mustEndNow!=1) @@ -1358,11 +1387,29 @@ CreateBibleGUI(msg2Display, isBibleQuote:=0, centerMsg:=0, noAdds:=0) { WinSet, Transparent, 1, ChurchTowerBibleWin WinGetPos,,, mainWid, mainHeig, ahk_id %hBibleOSD% - If (isBibleQuote=0 && InStr(msg2Display, ":") && !InStr(msg2Display, "`n")) + If (isBibleQuote=0 && InStr(msg2Display, ":") && !InStr(msg2Display, "`n") && showOSDprogressBar>1) { - percentileDay := Round(getPercentOfToday() * 100) "%" + If (showOSDprogressBar=2) + { + percu := Round(getPercentOfToday() * 100) + } Else If (showOSDprogressBar=3) + { + moonPhase := MoonPhaseCalculator() + percu := Round(moonPhase[3] * 100) + } Else If (showOSDprogressBar=4) + { + percu := Round((A_MDay/31) * 100) + } Else If (showOSDprogressBar=5) + { + percu := Round(getPercentOfAstroSeason() * 100) + } Else If (showOSDprogressBar=6) + { + percu := Round((A_YDay/366) * 100) + } + hu := Ceil(mainHeig*0.04 + 1) - Gui, BibleGui: Add, Progress, x0 y0 w%mainWid% h%hu% c%OSDfadedColor% background%OSDbgrColor%, % percentileDay + coloru := (percu=25 || percu=49 || percu=50 || percu=51 || percu=75) ? OSDtextColor : OSDfadedColor + Gui, BibleGui: Add, Progress, x0 y0 w%mainWid% h%hu% c%coloru% background%OSDbgrColor%, % percu "%" } If (centerMsg=1) @@ -1951,12 +1998,6 @@ ReloadScript(silent:=1) { attempts2Quit++ DoGuiFader := 1 - If (PrefOpen=1) - { - CloseSettings() - Return - } - DestroyBibleGui(A_ThisFunc) If FileExist(ThisFile) { @@ -1974,6 +2015,7 @@ ReloadScript(silent:=1) { } DeleteSettings() { + Gui, SettingsGUIA: +OwnDialogs MsgBox, 4, %appName%, Are you sure you want to delete the stored settings? IfMsgBox, Yes { @@ -2442,6 +2484,11 @@ checkBoxStrikeAdditional() { MCXI_Play(SNDmedia_auxil_bell) } +BtnHelpOrderedDisplay() { + Gui, SettingsGUIA: +OwnDialogs + MsgBox, , % "Help: " appName, Please select the option "Define start point" to set the index of the verse from which to begin displaying verses at the specified frequency. If the option is activated`, the verses will be displayed in the order they appear in the selected Bible`, otherwise the verse to be displayed will be chosen randomly. +} + ShowSettings() { doNotOpen := initSettingsWindow() If (doNotOpen=1) @@ -2453,7 +2500,7 @@ ShowSettings() { Global CurrentPrefWindow := 5 Global DoNotRepeatTimer := A_TickCount Global editF1, editF2, editF3, editF4, editF5, editF6, Btn1, volLevel, editF40, editF60, editF73, Btn2, txt4, Btn3, editF99, txt100 - , editF7, editF8, editF9, editF10, editF11, editF13, editF35, editF36, editF37, editF38, txt1, txt2, txt3, txt10, Btn4 + , editF7, editF8, editF9, editF10, editF11, editF13, editF35, editF36, editF37, editF38, txt1, txt2, txt3, txt10, Btn4, Btn5 columnBpos1 := columnBpos2 := 160 editFieldWid := 220 btnWid := 90 @@ -2480,28 +2527,31 @@ ShowSettings() { Gui, Add, Checkbox, y+10 gcheckBoxStrikeQuarter Checked%tollQuarters% vtollQuarters, Strike quarter-hours Gui, Add, Checkbox, x+10 gVerifyTheOptions Checked%tollQuartersException% vtollQuartersException, ... except on the hour Gui, Add, Checkbox, xs y+10 gcheckBoxStrikeHours Checked%tollHours% vtollHours, Strike on the hour - Gui, Add, Checkbox, x+10 gVerifyTheOptions Checked%tollHoursAmount% vtollHoursAmount, ... the number of hours + Gui, Add, Checkbox, x+10 gVerifyTheOptions Checked%tollHoursAmount% vtollHoursAmount, ... and the number of hours Gui, Add, Checkbox, xs y+10 gcheckBoxStrikeAdditional Checked%AdditionalStrikes% vAdditionalStrikes, Additional strike every (in minutes) Gui, Add, Edit, x+5 w65 geditsOSDwin r1 limit3 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF38, %strikeEveryMin% Gui, Add, UpDown, gVerifyTheOptions vstrikeEveryMin Range1-720, %strikeEveryMin% + Gui, Add, Checkbox, xs y+10 gVerifyTheOptions Checked%markFullMoonHowls% vmarkFullMoonHowls, Mark full moon by wolves howling Gui, Add, Text, xs y+10, Interval between tower strikes (in miliseconds): Gui, Add, Edit, x+5 w70 geditsOSDwin r1 limit5 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF37, %strikeInterval% Gui, Add, UpDown, gVerifyTheOptions vstrikeInterval Range900-5500, %strikeInterval% - wu := (PrefsLargeFonts=1) ? 125:95 - vu := (PrefsLargeFonts=1) ? 55:45 + wu := (PrefsLargeFonts=1) ? 125 : 95 + vu := (PrefsLargeFonts=1) ? 55 : 45 + mf := (PrefsLargeFonts=1) ? 260 : 193 Gui, Tab, 2 ; extras Gui, Add, Checkbox, x+15 y+15 Section gVerifyTheOptions Checked%showBibleQuotes% vshowBibleQuotes, Show a Bible verse every (in hours) Gui, Add, Edit, x+10 w65 geditsOSDwin r1 limit2 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF40, %BibleQuotesInterval% Gui, Add, UpDown, gVerifyTheOptions vBibleQuotesInterval Range1-12, %BibleQuotesInterval% - Gui, Add, DropDownList, xs+15 y+7 w270 gVerifyTheOptions AltSubmit Choose%BibleQuotesLang% vBibleQuotesLang, World English Bible (2000)|Français: Louis Segond (1910)|Español: Reina Valera (1909) + Gui, Add, DropDownList, xs+15 y+7 w%mf% gVerifyTheOptions AltSubmit Choose%BibleQuotesLang% vBibleQuotesLang, World English Bible (2000)|Français: Louis Segond (1910)|Español: Reina Valera (1909) + Gui, Add, Checkbox, x+5 hp gVerifyTheOptions Checked%orderedBibleQuotes% vorderedBibleQuotes, Define the start point Gui, Add, Text, xs+15 y+10 vTxt10, Font size Gui, Add, Edit, x+10 w%vu% geditsOSDwin r1 limit3 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF73, %FontSizeQuotes% Gui, Add, UpDown, gVerifyTheOptions vFontSizeQuotes Range10-200, %FontSizeQuotes% Gui, Add, Button, x+10 hp w%wu% gInvokeBibleQuoteNow vBtn2, Preview verse Gui, Add, Edit, x+10 w%vu% r1 limit5 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF4, % userBibleStartPoint Gui, Add, UpDown, gVerifyTheOptions vuserBibleStartPoint Range1-27400, % userBibleStartPoint - Gui, Add, Checkbox, x+5 gVerifyTheOptions Checked%orderedBibleQuotes% vorderedBibleQuotes, Define start point + Gui, Add, Button, x+5 hp w40 gBtnHelpOrderedDisplay vBtn5, ? Gui, Add, Text, xs+15 y+10 vTxt4, Maximum line length (in characters) Gui, Add, Edit, x+10 w%vu% geditsOSDwin r1 limit3 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF60, %maxBibleLength% Gui, Add, UpDown, vmaxBibleLength gVerifyTheOptions Range20-130, %maxBibleLength% @@ -2552,6 +2602,7 @@ ShowSettings() { Gui, Add, Checkbox, xs y+15 h25 +0x1000 gVerifyTheOptions Checked%ShowPreview% vShowPreview, Show preview window Gui, Add, Checkbox, x+5 hp gVerifyTheOptions Checked%ShowPreviewDate% vShowPreviewDate, Include current date + mf := (PrefsLargeFonts=1) ? 170 : 143 Gui, Add, DropDownList, xs+%columnBpos2% ys+0 section w205 gVerifyTheOptions Sort Choose1 vFontName, %FontName% Gui, Add, ListView, xp+0 yp+30 w55 h25 %CCLVO% Background%OSDtextColor% vOSDtextColor hwndhLV1, Gui, Add, ListView, x+5 yp w55 h25 %CCLVO% Background%OSDbgrColor% vOSDbgrColor hwndhLV2, @@ -2559,12 +2610,13 @@ ShowSettings() { Gui, Add, UpDown, vOSDalpha gVerifyTheOptions Range75-250, %OSDalpha% Gui, Add, Edit, xp-120 yp+30 w55 geditsOSDwin r1 limit3 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF5, %FontSize% Gui, Add, UpDown, gVerifyTheOptions vFontSize Range12-295, %FontSize% - Gui, Add, Edit, xp yp+30 w55 hp geditsOSDwin r1 limit2 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF99, %showTimeIdleAfter% + Gui, Add, DropDownList, x+5 w%mf% gVerifyTheOptions AltSubmit Choose%showOSDprogressBar% vshowOSDprogressBar, No progress bar|Current day|Moon`'s synodic period|Current month|Astronomical seasons|Current year + Gui, Add, Edit, xp-60 yp+30 w55 hp geditsOSDwin r1 limit2 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF99, %showTimeIdleAfter% Gui, Add, UpDown, vshowTimeIdleAfter gVerifyTheOptions Range1-950, %showTimeIdleAfter% Gui, Add, Text, x+5 vtxt100, idle time (in min.) Gui, Add, Edit, xs yp+30 w55 hp geditsOSDwin r1 limit2 -multi number -wantCtrlA -wantReturn -wantTab -wrap veditF6, %DisplayTimeUser% Gui, Add, UpDown, vDisplayTimeUser gVerifyTheOptions Range1-99, %DisplayTimeUser% - Gui, Add, Checkbox, x+10 hp gVerifyTheOptions Checked%OSDroundCorners% vOSDroundCorners, Round corners + Gui, Add, Checkbox, x+5 hp gVerifyTheOptions Checked%OSDroundCorners% vOSDroundCorners, Round corners If !FontList._NewEnum()[k, v] { Fnt_GetListOfFonts() @@ -2591,6 +2643,7 @@ ShowSettings() { VerifyTheOptions(EnableApply:=1,forceNoPreview:=0) { Gui, SettingsGUIA: Default GuiControlGet, ShowPreview + GuiControlGet, markFullMoonHowls GuiControlGet, silentHours GuiControlGet, tollHours GuiControlGet, tollQuarters @@ -2602,6 +2655,7 @@ VerifyTheOptions(EnableApply:=1,forceNoPreview:=0) { GuiControlGet, maxBibleLength GuiControlGet, BibleQuotesLang GuiControlGet, displayClock + GuiControlGet, showOSDprogressBar GuiControlGet, analogDisplay GuiControlGet, showTimeIdleAfter GuiControlGet, showTimeWhenIdle @@ -2618,6 +2672,7 @@ VerifyTheOptions(EnableApply:=1,forceNoPreview:=0) { GuiControl, % (showBibleQuotes=0 ? "Disable" : "Enable"), Txt4 GuiControl, % (showBibleQuotes=0 ? "Disable" : "Enable"), makeScreenDark GuiControl, % (showBibleQuotes=0 ? "Disable" : "Enable"), BibleQuotesLang + GuiControl, % (showBibleQuotes=0 ? "Disable" : "Enable"), Btn5 GuiControl, % (showBibleQuotes=0 ? "Disable" : "Enable"), noBibleQuoteMhidden GuiControl, % (showBibleQuotes=0 ? "Disable" : "Enable"), orderedBibleQuotes GuiControl, % (showBibleQuotes=0 || orderedBibleQuotes-1) ? "Disable" : "Enable", userBibleStartPoint @@ -3028,9 +3083,7 @@ coreTestCelebrations(thisMon, thisMDay, thisYDay, isListMode) { lifeGivingSpring(aisHolidayToday, thisYDay) holyTrinityOrthdox(aisHolidayToday, thisYDay) - If (testFeast="01.01" && UserReligion=1) - q := "Commemoration of the Blessed Virgin Mary as Mother of God (Θεοτόκος) as proclaimed in the Council of Ephesus (431). Also the octave of Christmas traditionally commemorating the circumcision of the Lord Jesus Christ" - Else If (testFeast="01.06") + If (testFeast="01.06") q := (UserReligion=1) ? "Epiphany - the revelation of God incarnate as Jesus Christ" : "Theophany - the baptism of Jesus in the Jordan River" Else If (testFeast="01.07" && UserReligion=2) q := "Synaxis of Saint John the Baptist - a Jewish itinerant preacher, and a prophet" @@ -3038,16 +3091,12 @@ coreTestCelebrations(thisMon, thisMDay, thisYDay, isListMode) { q := "The Three Holy Hierarchs - Basil the Great, John Chrysostom and Gregory the Theologian" Else If (testFeast="02.02") q := "Presentation of the Lord Jesus Christ - at the Temple in Jerusalem to induct Him into Judaism, episode described in the 2nd chapter of the Gospel of Luke" - Else If (testFeast="03.19" && !aisHolidayToday) - q := "Saint Joseph's Day - Spouse of the Blessed Virgin Mary and legal father of the Lord Jesus Christ" Else If (testFeast="03.25" && !aisHolidayToday) q := "Annunciation of the Lord Jesus Christ - when the Blessed Virgin Mary was told she would conceive and become the mother of Jesus of Nazareth" Else If (testFeast="04.23" && !aisHolidayToday) q := "Saint George - a Roman soldier of Greek origin under the Roman emperor Diocletian, sentenced to death for refusing to recant his Christian faith, venerated as a military saint since the Crusades." Else If (testFeast="06.24") q := "Birth of Saint John the Baptist - a Jewish itinerant preacher, and a prophet known for having anticipated a messianic figure greater than himself" - Else If (testFeast="06.29") - q := "Solemnity of the Apostles Peter and Paul - Both martyred in Rome, St. Peter, the first Pope, was crucified upsidedown and St. Paul, the apostle of the Gentiles, was beheaded" Else If (testFeast="08.06") aisHolidayToday := "Feast of the Transfiguration of the Lord Jesus Christ - when He becomes radiant in glory upon Mount Tabor" Else If (testFeast="08.15") @@ -3059,9 +3108,11 @@ coreTestCelebrations(thisMon, thisMDay, thisYDay, isListMode) { Else If (testFeast="09.14") q := "Exaltation of the Holy Cross - the recovery of the cross on which Jesus Christ was crucified by the Roman government on the order of Pontius Pilate" Else If (testFeast="10.04" && UserReligion=1) - q := "Saint Francis of Assisi - an Italian friar, deacon, preacher and founder of the Friar Minors (OFM), the Poor Clares and the Third Order of Saint Francis within the Catholic church who lived between 1182 and 1226" + q := "Saint Francis of Assisi - an Italian friar, deacon, preacher and founder of the Friar Minors (OFM) within the Catholic church who lived between 1182 and 1226" Else If (testFeast="10.14" && UserReligion=2) q := "Saint Paraskeva of the Balkans - an ascetic female saint of the 10th century of half Serbian and half Greek origins" + Else If (testFeast="10.31" && UserReligion=1) + q := "All Hallows' Eve - the eve of the Solemnity of All Saints" Else If (testFeast="11.01" && UserReligion=1) q := "All Saints' day - a commemoration day for all Christian saints" Else If (testFeast="11.02" && UserReligion=1) @@ -3106,7 +3157,6 @@ coreTestCelebrations(thisMon, thisMDay, thisYDay, isListMode) { . "International Literacy Day|09.08`n" . "International Day of Peace|09.21`n" . "International Day for the Universal Access to Information [for people with disabilities]|09.28`n" - . "Halloween (All Hallows' Eve)|10.31`n" . "Armistice Day (also Remembrance Day or Veterans Day) - recalling the victims of World War I|11.11`n" . "International Day for Tolerance|11.16`n" . "International Day for the Elimination of Violence against Women|11.25`n" @@ -3169,6 +3219,7 @@ OpenListCelebrationsBtn() { celebYear := A_Year If (PrefOpen=1 && hSetWinGui) VerifyTheOptions() + PanelManageCelebrations() } @@ -3238,16 +3289,13 @@ updateOptionsLVsGui() { } updateHolidaysLVs() { - Static MaterDei := "01.01" - , Epiphany := "01.06" + Static Epiphany := "01.06" , SynaxisSaintJohnBaptist := "01.07" , ThreeHolyHierarchs := "01.30" , PresentationLord := "02.02" - , SaintJoseph := "03.19" , AnnunciationLord := "03.25" , SaintGeorge := "04.23" , BirthJohnBaptist := "06.24" - , SsPeterAndPaul :="06.29" , FeastTransfiguration := "08.06" , AssumptionVirginMary := "08.15" , BeheadingJohnBaptist := "08.29" @@ -3255,6 +3303,7 @@ updateHolidaysLVs() { , ExaltationHolyCross := "09.14" , SaintFrancisAssisi := "10.04" , SaintParaskeva := "10.14" + , HalloweenDay := "10.31" , Allsaintsday := "11.01" , Allsoulsday := "11.02" , PresentationVirginMary := "11.21" @@ -3297,7 +3346,7 @@ updateHolidaysLVs() { . "Good Friday|" goodFridaydate "`n" . "Holy Saturday|" HolySaturdaydate "`n" . "Catholic Easter|" easterdate "`n" - . "Catholic Easter Monday|" 2ndeasterdate "`n" + . "Catholic Easter - 2nd day|" 2ndeasterdate "`n" . "Divine Mercy|" divineMercyDate "`n" . "Ascension of Jesus|" ascensiondaydate "`n" . "Pentecost|" pentecostdate "`n" @@ -3307,20 +3356,18 @@ updateHolidaysLVs() { Gui, ListView, LViewEaster processHolidaysList(theList) - Static theList2 := "Divine Maternity of the Blessed Virgin Mary|" MaterDei "`n" - . "Epiphany|" Epiphany "`n" + Static theList2 := "Epiphany|" Epiphany "`n" . "Presentation of the Lord Jesus Christ|" PresentationLord "`n" - . "Saint Joseph's Day|" SaintJoseph "`n" . "Annunciation of the Blessed Virgin Mary|" AnnunciationLord "`n" . "Saint George|" SaintGeorge "`n" . "Birth of Saint John the Baptist|" BirthJohnBaptist "`n" - . "Solemnity of Saints Peter and Paul|" SsPeterAndPaul "`n" . "Transfiguration of the Lord Jesus Christ|" FeastTransfiguration "`n" . "Assumption of the Blessed Virgin Mary|" AssumptionVirginMary "`n" . "Beheading of Saint John the Baptist|" BeheadingJohnBaptist "`n" . "Birth of the Blessed Virgin Mary|" BirthVirginMary "`n" . "Exaltation of the Holy Cross|" ExaltationHolyCross "`n" . "Saint Francis of Assisi|" SaintFrancisAssisi "`n" + . "All Hallows' Eve [Hallowe'en]|" HalloweenDay "`n" . "All Saints' day|" Allsaintsday "`n" . "All souls' day|" Allsoulsday "`n" . "Presentation of the Blessed Virgin Mary|" PresentationVirginMary "`n" @@ -3340,7 +3387,7 @@ updateHolidaysLVs() { . "Holy Friday|" goodFridaydate "`n" . "Holy Saturday|" HolySaturdaydate "`n" . "Orthodox Easter|" easterdate "`n" - . "Orthodox Easter Monday|" 2ndeasterdate "`n" + . "Orthodox Easter - 2nd day|" 2ndeasterdate "`n" . "Life-Giving Spring|" lifeSpringDate "`n" . "Ascension of Jesus|" ascensiondaydate "`n" . "Pentecost|" pentecostdate "`n" @@ -3401,7 +3448,6 @@ updateHolidaysLVs() { . "Literacy Day|09.08`n" . "International Day of Peace|09.21`n" . "Day for the Universal Access to Information|09.28`n" - . "Halloween|10.31`n" . "Armistice Day / Remembrance Day / Veterans Day|11.11`n" . "Tolerance Day|11.16`n" . "Elimination of Violence Against Women|11.25`n" @@ -3584,6 +3630,7 @@ ActionListViewKBDs() { If (A_TickCount - lastAsked>4000) { answerPositive := 0 + Gui, CelebrationsGuia: +OwnDialogs MsgBox, 36, %appName%, %questionMsg% IfMsgBox, Yes { @@ -3610,6 +3657,7 @@ ActionListViewKBDs() { If (A_TickCount - lastAsked>2000) { answerPositive := 0 + Gui, CelebrationsGuia: +OwnDialogs MsgBox, 36, %appName%, %questionMsg% IfMsgBox, Yes { @@ -3704,7 +3752,94 @@ CancelNewEntryBtn() { PanelManageCelebrations(4) } -compareYearDays(givenDay, CurrentDay) { +wrapCalculateEquiSolsDates() { + Critical, on + Static lastInvoked := 1, prevYear := 0, prevBias := -1, prevDay := 0, TZI := [], z := [] + + startZeit := A_TickCount + If (prevDay!=A_YDay || prevBias=-1) + { + TZI := TZI_GetTimeZoneInformation() + prevBias := -1 * TZI.TotalCurrentBias + prevDay := A_YDay + } + + If (InStr(EquiSolsCache, "|") && prevYear!=A_Year) + { + arrayu := StrSplit(EquiSolsCache, "|", "`r") + mEquiDay := arrayu[1] + mEquiDate := arrayu[2] + jSolsDay := arrayu[3] + jSolsDate := arrayu[4] + sEquiDay := arrayu[5] + sEquiDate := arrayu[6] + dSolsDay := arrayu[7] + dSolsDate := arrayu[8] + prevYear := arrayu[9] + If (arrayu[10]!=prevBias) + prevYear := 0 + } + + If (prevYear!=A_Year) + { + Loop, 4 + { + k := calculateEquiSols(A_Index, A_Year, 0) + FormatTime, OutputVar, % k, Yday + thisBias := isinRange(OutputVar, TZI.DaylightDateYday, TZI.StandardDateYday) ? TZI.Bias + TZI.DaylightBias + TZI.StandardBias : TZI.Bias + TZI.StandardBias + thisBias := -1*thisBias + k += thisBias, M + FormatTime, OutputVar, % k, Yday + If (A_Index=1 && OutputVar>70) + { + mEquiDay := OutputVar + mEquiDate := k + } Else If (A_Index=2 && OutputVar>165) + { + jSolsDay := OutputVar + jSolsDate := k + } Else If (A_Index=3 && OutputVar>260) + { + sEquiDay := OutputVar + sEquiDate := k + } Else If (A_Index=4 && OutputVar>350) + { + dSolsDay := OutputVar + dSolsDate := k + } + ; fnOutputDebug(A_Index "=" k "==" OutputVar) + } + + EquiSolsCache := mEquiDay "|" mEquiDate "|" jSolsDay "|" jSolsDate "|" sEquiDay "|" sEquiDate "|" dSolsDay "|" dSolsDate "|" A_Year "|" prevBias + INIaction(1, "EquiSolsCache", "SavedSettings") + prevYear := A_Year + } + + If (A_TickCount - lastInvoked<9500) + Return z + + z := [] + z.MarchEquinox := giveYearDayProximity(mEquiDay, A_YDay) . "March equinox." ; 03 / 20 + z.JuneSolstice := giveYearDayProximity(jSolsDay, A_YDay) . "June solstice." ; 06 / 21 + z.SepEquinox := giveYearDayProximity(sEquiDay, A_YDay) . "September equinox." ; 09 / 22 + z.DecSolstice := giveYearDayProximity(dSolsDay, A_YDay) . "December solstice." ; 12 / 21 + If InStr(z.MarchEquinox, "now") + z.r := 1 + Else If InStr(z.JuneSolstice, "now") + z.r := 2 + Else If InStr(z.SepEquinox, "now") + z.r := 3 + Else If InStr(z.DecSolstice, "now") + z.r := 4 + + lastInvoked := A_TickCount + endZeit := A_TickCount - startZeit + ; ToolTip, % endzeit , , , 2 + Return z +} + +giveYearDayProximity(givenDay, CurrentDay) { + If (CurrentDay>givenDay) { passedDays := CurrentDay - givenDay @@ -3717,8 +3852,9 @@ compareYearDays(givenDay, CurrentDay) { Result := Floor(Weeksz)=1 ? "One week" : Floor(Weeksz) " weeks" } Else If (passedDays>2) Result := "Less than a week" + Result .= " since the " - If (passedDays<=2) + If (passedDays<2) Result := "now" } Else { @@ -3733,7 +3869,7 @@ compareYearDays(givenDay, CurrentDay) { } Else If (DaysUntil>2) Result := "Less than a week" Result .= " until the " - If (DaysUntil<=2) + If (DaysUntil<2) Result := "now" } If (Floor(Weeksz)>=4) @@ -3744,21 +3880,14 @@ compareYearDays(givenDay, CurrentDay) { testEquiSols() { OSDsuffix := "" - - MarchEquinox := compareYearDays(78, A_YDay) - If InStr(MarchEquinox, "now") + testu := wrapCalculateEquiSolsDates() + If (testu.r=1) OSDsuffix := " ▀" - - JuneSols := compareYearDays(170, A_YDay) - If InStr(JuneSols, "now") + Else If (testu.r=2) OSDsuffix := " ⬤" - - SepEquinox := compareYearDays(263, A_YDay) - If InStr(SepEquinox, "now") + Else If (testu.r=3) OSDsuffix := " ▃" - - DecSols := compareYearDays(354, A_YDay) - If InStr(DecSols, "now") + Else If (testu.r=4) OSDsuffix := " ◯" testFeast := A_Mon "." A_MDay @@ -3776,12 +3905,12 @@ PanelIncomingCelebrations() { INIaction(1, "LastWinOpened", "SavedSettings") btnWid := 100 txtWid := 360 - Global btn1 + Global holiListu, btn1, txtLine Gui, Font, c%AboutTitleColor% s20 Bold, Arial, -wrap Gui, Add, Picture, x15 y15 w55 h-1 +0x3 Section gTollExtraNoon hwndhBellIcon, bell-image.png Gui, Add, Text, x+7 y10, %appName% Gui, Font, s12 Bold, Arial, -wrap - Gui, Add, Text, y+4, Celebrations in the next 30 days. + Gui, Add, Text, y+4 vtxtLine, Celebrations in the next 30 days. doResetGuiFont() If (PrefsLargeFonts=1) { @@ -3792,6 +3921,21 @@ PanelIncomingCelebrations() { If (tickTockNoise!=1) SoundLoop(tickTockSound) + btnW1 := (PrefsLargeFonts=1) ? 105 : 80 + btnH := (PrefsLargeFonts=1) ? 35 : 28 + Gui, Add, Button, xs+1 y+15 w1 h1, L + Gui, Add, Edit, xp+1 yp+1 ReadOnly r15 w%txtWid% vholiListu, % listu + Gui, Font, Normal + Gui, Add, Button, xs+0 y+20 h%btnH% w%btnW1% Default gOpenListCelebrationsBtn hwndhBtn1, &Manage + Gui, Add, Button, x+5 hp wp+15 gShowSettings hwndhBtn2, &Settings + Gui, Add, Button, x+5 hp wp-15 gCloseWindow hwndhBtn3, &Close + applyDarkMode2winPost("SettingsGUIA", hSetWinGui) + Gui, Show, AutoSize, Celebrations list: %appName% + PopulateIncomingCelebs() +} + +PopulateIncomingCelebs() { + startDate := "" listu := "" If (StrLen(isHolidayToday)>2 && ObserveHolidays=1) @@ -3805,9 +3949,7 @@ PanelIncomingCelebrations() { } startYday := A_YDay - PersonalDate := A_Year 0229010101 - FormatTime, PersonalDate, %PersonalDate%, LongDate - totalYDays := StrLen(PersonalDate)>3 ? 366 : 365 + totalYDays := isLeapYear() ? 366 : 365 Loop, 30 { startDate += 1, Days @@ -3823,17 +3965,40 @@ PanelIncomingCelebrations() { listu .= thisYear "/" thisMon "/" thisMDay " = " obju[2] "`n`n" } - Global holiListu - btnW1 := (PrefsLargeFonts=1) ? 105 : 80 - btnH := (PrefsLargeFonts=1) ? 35 : 28 - Gui, Add, Button, xs+1 y+15 w1 h1, L - Gui, Add, Edit, xp+1 yp+1 ReadOnly r15 w%txtWid% vholiListu, % listu - Gui, Font, Normal - Gui, Add, Button, xs+0 y+20 h%btnH% w%btnW1% Default gOpenListCelebrationsBtn hwndhBtn1, &Manage - Gui, Add, Button, x+5 hp wp+15 gShowSettings hwndhBtn2, &Settings - Gui, Add, Button, x+5 hp wp-15 gCloseWindow hwndhBtn3, &Close - applyDarkMode2winPost("SettingsGUIA", hSetWinGui) - Gui, Show, AutoSize, Celebrations list: %appName% + listu .= "Astronomic events:`n`n" + FormatTime, OutputVar, % mEquiDate, yyyy/MM/dd + If isinRange(mEquiDay, A_YDay, A_YDay + 30) + listu .= OutputVar " = March Equinox`n`n" + + FormatTime, OutputVar, % jSolsDate, yyyy/MM/dd + If isinRange(jSolsDay, A_YDay, A_YDay + 30) + listu .= OutputVar " = June Solstice`n`n" + + FormatTime, OutputVar, % sEquiDate, yyyy/MM/dd + If isinRange(sEquiDay, A_YDay, A_YDay + 30) + listu .= OutputVar " = September Equinox`n`n" + + FormatTime, OutputVar, % dSolsDate, yyyy/MM/dd + If isinRange(dSolsDay, A_YDay, A_YDay + 30) + listu .= OutputVar " = December Solstice`n`n" + + startDate := A_Year A_Mon A_MDay 010101 + ; startDate := 2022 01 01 010101 + listuA := listuB := "" + Loop, 30 + { + startDate += 1, Days + pk := MoonPhaseCalculator(startDate) + If (prevu!=pk[1] && !InStr(pk[1], "peak") && (InStr(pk[1], "full") || InStr(pk[1], "new"))) + { + prevu := pk[1] + FormatTime, OutputVar, % startDate, yyyy/MM/dd + listu .= OutputVar " = " pk[1] "`n`n" + ; listu .= OutputVar " = " pk[1] "`n p=" pk[3] "; f=" pk[4] "; a=" pk[5] " `n" + } + } + + GuiControl, SettingsGUIA:, holiListu, % listu listuB listuA } reactWinOpened(funcu, idu) { @@ -4214,7 +4379,6 @@ uiStopWatchUpdater() { GuiControl, SettingsGUIA:, UIstopWatchInterval, %hrz%.%SecB% GuiControl, SettingsGUIA:, UIstopWatchDetailsInterval, (%labelu% lap) - If (stopWatchIntervalInfos[3]>0) { allLapsZeit := thisLap @@ -4518,13 +4682,66 @@ startAlarmTimer() { SetTimer, doUserAlarmAlert, % -newu*1000 } +getPercentOfAstroSeason(z:=0) { + ; Static t := 0 + td := isLeapYear() ? 366 : 365 + t := (z>0) ? z : A_YDay + ; t += 5 + ; If (t>366) + ; t := 0 + + If (t>dSolsDay) + { + c := 4 + dayz := td - dSolsDay + mEquiDay + passedDayz := td - t + mEquiDay + } Else If (t<=mEquiDay) + { + c := 5 + dayz := td - dSolsDay + mEquiDay + passedDayz := t + (td - dSolsDay) + } Else If (t>sEquiDay) + { + c := 3 + dayz := dSolsDay - sEquiDay + passedDayz := dSolsDay - t + } Else If (t>jSolsDay) + { + c := 2 + dayz := sEquiDay - jSolsDay + passedDayz := sEquiDay - t + } Else If (t>mEquiDay) + { + c := 1 + dayz := jSolsDay - mEquiDay + passedDayz := jSolsDay - t + } + If (c!=5) + passedDayz := dayz - passedDayz + + r := passedDayz / dayz + ; ToolTip, % "td=" td " | " t "=" c "`n" passedDayz "//" dayz "=" r , , , 2 + Return r +} + getPercentOfToday(ByRef minsPassed:=0) { FormatTime, CurrentDateTime,, yyyyMMddHHmm FormatTime, CurrentDay,, yyyyMMdd FirstMinOfDay := CurrentDay "0001" EnvSub, CurrentDateTime, %FirstMinOfDay%, Minutes minsPassed := CurrentDateTime + 1 - Return minsPassed/1450 + Return minsPassed/1445 +} + +fnOutputDebug(msg) { + OutputDebug, % "QPV: " Trim(msg) +} + +isLeapYear(thisYear:=0) { + PersonalDate := (thisYear>0) ? thisYear 0229010101 : A_Year 0229010101 + FormatTime, PersonalDate, %PersonalDate%, LongDate + r := (StrLen(PersonalDate)>3) ? 1 : 0 + Return r } PanelAboutWindow() { @@ -4573,18 +4790,11 @@ PanelAboutWindow() { Gui, Add, Tab3,xm+1, Today|Application details Gui, Tab, 1 testCelebrations() - MarchEquinox := compareYearDays(78, A_YDay) "March equinox." ; 03 / 20 - If InStr(MarchEquinox, "now") - MarchEquinox := "(" OSDsuffix " ) The March equinox is here now. Day and night times are balanced for a few days." - JuneSolstice := compareYearDays(170, A_YDay) "June solstice. " ; 06 / 21 - If InStr(JuneSolstice, "now") - JuneSolstice := "(" OSDsuffix " ) The June solstice is here now. Today is one of the longest days of the year." - SepEquinox := compareYearDays(263, A_YDay) "September equinox." ; 09 / 22 - If InStr(SepEquinox, "now") - SepEquinox := "(" OSDsuffix " ) The September equinox is here now. Day and night times are balanced for a few days." - DecSolstice := compareYearDays(354, A_YDay) "December solstice." ; 12 / 21 - If InStr(DecSolstice, "now") - DecSolstice := "(" OSDsuffix " ) The December solstice is here now. Today is one of the shortest days of the year." + zx := wrapCalculateEquiSolsDates() + MarchEquinox := !InStr(zx.MarchEquinox, "now") ? zx.MarchEquinox : "(" OSDsuffix " ) March equinox. The day and night are everywhere on Earth of approximately equal length." + JuneSolstice := !InStr(zx.JuneSolstice, "now") ? zx.JuneSolstice : "(" OSDsuffix " ) June solstice. Today is one of the longest days of the year." + SepEquinox := !InStr(zx.SepEquinox, "now") ? zx.SepEquinox : "(" OSDsuffix " ) September equinox. The day and night are everywhere on Earth of approximately equal length." + DecSolstice := !InStr(zx.DecSolstice, "now") ? zx.DecSolstice : "(" OSDsuffix " ) December solstice. Today is one of the shortest days of the year." percentileYear := Round(A_YDay/366*100) "%" FormatTime, CurrentYear,, yyyy @@ -4649,18 +4859,16 @@ PanelAboutWindow() { testFeast := A_Mon "." A_MDay If (testFeast="01.01") || (testFeast="02.01") { - PersonalDate := A_Year 0229010101 - FormatTime, PersonalDate, %PersonalDate%, LongDate - If (StrLen(PersonalDate)>3) + If isLeapYear() Gui, Add, Text, y+7 w%txtWid%, %A_Year% is a leap year. } Else If (testFeast="02.29") Gui, Add, Text, y+7 w%txtWid%, Today is the 29th of February - a leap year day. Gui, Font, Normal If (A_YDay>172 && A_YDay<352) - Gui, Add, Text, y+7, The days are getting shorter until the winter solstice, in December. + Gui, Add, Text, y+7, The days are getting shorter until the December solstice. Else If (A_YDay>356 || A_YDay<167) - Gui, Add, Text, y+7, The days are getting longer until the summer solstice, in June. + Gui, Add, Text, y+7, The days are getting longer until the June solstice. If (A_OSVersion="WIN_XP") { @@ -4671,12 +4879,28 @@ PanelAboutWindow() { Gui, Font,, DejaVu LGC Sans } - moonPhase := MoonPhaseCalculator(A_Year, A_Mon, A_MDay) + ; fnOutputDebug("booooooooooooooooooooom") + moonPhase := MoonPhaseCalculator() moonPhaseN := moonPhase[1] - moonPhaseF := Round(moonPhase[3] * 100) + moonPhaseI := moonPhase[2] + moonPhaseC := Round(moonPhase[3] * 100) + moonPhaseL := Round(moonPhase[4] * 100) + + ; startDate := 2022 01 01 010101 + ; Loop, 983 + ; { + ; startDate += 1, Hours + ; pk := MoonPhaseCalculator(startDate) + ; FormatTime, OutputVar, % startDate, yyyy/MM/dd + ; ; listu .= OutputVar " = " pk[1] "`n`n" + ; ; If InStr(pk[1], "new") + ; fnOutputDebug(OutputVar " = " pk[1] "; p=" pk[3] "; f=" pk[4] "; a=" pk[5]) + ; } + Gui, Add, Text, xp+30 y+15 Section, % CurrentYear " {" CalcTextHorizPrev(A_YDay, 366) "} " NextYear Gui, Add, Text, xp+15 y+5, %weeksPassed% %weeksPlural% (%percentileYear%) of %CurrentYear% %weeksPlural2% elapsed. - Gui, Add, Text, xs y+10, Moon phase: %moonPhaseN% (%moonPhaseF%`% of the cycle). + Gui, Add, Text, xs y+10, Moon phase: %moonPhaseN% (%moonPhaseI% / 8) + Gui, Add, Text, xp+15 y+10, %moonPhaseC%`% of the cycle, %moonPhaseL%`% illuminated. Gui, Add, Text, xs y+10, % "0h {" CalcTextHorizPrev(minsPassed, 1440, 0, 22) "} 24h " Gui, Add, Text, xp+15 y+5, %minsPassed% minutes (%percentileDay%) of today have elapsed. If (A_OSVersion="WIN_XP") @@ -4688,7 +4912,7 @@ PanelAboutWindow() { compiled := (A_IsCompiled=1) ? "Compiled. " : "Uncompiled. " compiled .= (A_PtrSize=8) ? "x64. " : "x32. " Gui, Add, Text, xs y+15 w%txtWid%, Current version: v%version% from %ReleaseDate%. Internal AHK version: %A_AhkVersion%. %compiled%OS: %A_OSVersion%. - Gui, Add, Text, y+15 gOpenChangeLog, Click here to view the change log / version history. + Gui, Add, Text, y+15 +Border gOpenChangeLog, Click here to view the change log / version history. If (storeSettingsREG=1) Gui, Add, Link, xs y+10 w%txtWid% hwndhLink2, This application was downloaded through Windows Store. Else @@ -4757,15 +4981,25 @@ INIaction(act, var, section) { If (storeSettingsREG=0) { If (act=1) + { IniWrite, %varValue%, %IniFile%, %section%, %var% - Else - IniRead, %var%, %IniFile%, %section%, %var%, %varValue% + } Else + { + IniRead, loaded, %IniFile%, %section%, %var%, %varValue% + If !ErrorLevel + %var% := loaded + } } Else { If (act=1) + { RegWrite, REG_SZ, %APPregEntry%, %var%, %varValue% - Else - RegRead, %var%, %APPregEntry%, %var% + } Else + { + RegRead, loaded, %APPregEntry%, %var% + If !ErrorLevel + %var% := loaded + } } } @@ -4793,7 +5027,11 @@ INIsettings(a) { INIaction(1, "FirstRun", "SavedSettings") INIaction(1, "ReleaseDate", "SavedSettings") INIaction(1, "Version", "SavedSettings") + } Else + { + INIaction(0, "EquiSolsCache", "SavedSettings") } + INIaction(a, "PrefsLargeFonts", "SavedSettings") INIaction(a, "LastWinOpened", "SavedSettings") INIaction(a, "LargeUIfontValue", "SavedSettings") @@ -4811,9 +5049,11 @@ INIsettings(a) { INIaction(a, "showTimeIdleAfter", "SavedSettings") INIaction(a, "showTimeWhenIdle", "SavedSettings") INIaction(a, "displayTimeFormat", "SavedSettings") + INIaction(a, "markFullMoonHowls", "SavedSettings") INIaction(a, "BeepsVolume", "SavedSettings") INIaction(a, "DynamicVolume", "SavedSettings") INIaction(a, "AutoUnmute", "SavedSettings") + INIaction(a, "hasHowledDay", "SavedSettings") INIaction(a, "userAlarmSound", "SavedSettings") INIaction(a, "userTimerSound", "SavedSettings") INIaction(a, "userMuteAllSounds", "SavedSettings") @@ -4871,6 +5111,7 @@ INIsettings(a) { INIaction(a, "OSDmarginBottom", "OSDprefs") INIaction(a, "OSDmarginSides", "OSDprefs") INIaction(a, "OSDroundCorners", "OSDprefs") + INIaction(a, "showOSDprogressBar", "OSDprefs") INIaction(a, "makeScreenDark", "SavedSettings") INIaction(a, "maxBibleLength", "OSDprefs") @@ -4927,6 +5168,7 @@ CheckSettings() { BinaryVar(makeScreenDark, 1) BinaryVar(noTollingWhenMhidden, 0) BinaryVar(noBibleQuoteMhidden, 1) + BinaryVar(markFullMoonHowls, 0) BinaryVar(SemantronHoliday, 0) BinaryVar(ObserveHolidays, 0) BinaryVar(ObserveReligiousDays, 1) @@ -4981,6 +5223,7 @@ CheckSettings() { MinMaxVar(userTimerMins, 0, 59, 2) MinMaxVar(userTimerFreq, 1, 99, 2) MinMaxVar(userAlarmFreq, 1, 99, 4) + MinMaxVar(showOSDprogressBar, 1, 6, 2) If (silentHoursB b, take integer part of jd - jd -= b ; subtract integer part to leave fractional part of original jd - b := jd * 8 ; scale fraction from 0-8 - if (b>=8) - b := 0 ; 0 and 8 are the same so turn 8 into 0 - perc := b/8 - Static phaseNames := {0:"〇 New Moon", 1:"Waxing Crescent Moon", 2:"◐ First Quarter Moon", 3:"Waxing Gibbous Moon", 4:"⚫ Full Moon", 5:"Waning Gibbous Moon", 6:"◑ Last Quarter Moon", 7:"Waning Crescent Moon"} - z := Round(b) - thisPhase := phaseNames[z] - return [thisPhase, b, perc] + B := SM_Add(A, 1524) + C := SM_Floor( SM_Divide(SM_Add(B, "-122.1"), 365.25, 90) ) + ; C := Floor( (B-122.1) / 365.25 ) + D := SM_Floor( SM_Multiply(365.25, C) ) + ; D := Floor( 365.25*C ) + E := SM_Floor( SM_Divide(SM_Add(B, -D), 30.6001) ) + ; E := Floor( ( B-D )/30.6001 ) + DT := SM_Add( SM_Add( SM_Add(B, -D), - SM_Floor( SM_Multiply(30.6001, E) ) ), F ) ; Day of Month with decimals for time + ; DT := B - D - Floor(30.6001*E) + F ; Day of Month with decimals for time + + G := (E < 13.5) ? 1 : 13 + Mon := SM_Add(E, -G) ; Month + G := (Mon > 2.5) ? 4716 : 4715 + Yr := SM_Add(C, -G) ; Year + Day := SM_Floor( DT ) ; Day of Month without decimals for time + H := SM_Multiply(24, SM_Add(DT, -Day) ) ; Hours and fractional hours + Hr := SM_Floor( H ) ; Integer Hours + M := SM_Multiply(60, SM_Add(H, -Hr) ) ; Minutes and fractional minutes + Min := SM_Floor( M ) ; Integer Minutes + Sec := SM_Floor( 60 * (M - Min) ) ; Integer Seconds (Milliseconds discarded) + + ; theDate := Yr "-" Mon "-" Day "-" Hr "-" Min "-" Sec + theDate := Yr Format("{:02}", Mon) Format("{:02}", Day) Format("{:02}", Hr) Format("{:02}", Min) Format("{:02}", Sec) + return theDate +} + +TZI_GetTimeZoneInformation() { + ; source https://gist.github.com/hoppfrosch/6882628 + ; and https://www.autohotkey.com/board/topic/68856-sample-dealing-with-time-zones-ahk-l/ + + ; GetTimeZoneInformationForYear -> msdn.microsoft.com/en-us/library/bb540851(v=vs.85).aspx (Win Vista+) + ; cmd.exe w32tm /tz + + Year := A_Year + VarSetCapacity(TZI, 172, 0) + If !DllCall("GetTimeZoneInformationForYear", "UShort", Year, "Ptr", 0, "Ptr", &TZI, "Int") + { + TZI := "" + Return 0 + } + + R := [] + R.Bias := NumGet(TZI, "Int") + R.StandardName := StrGet(&TZI + 4, 32, "UTF-16") + ST := New TZI_SYSTEMTIME(&TZI + 68) ; Calculate StandardDate TimeStamp + ; If ST.Year is not zero the date is fix. Otherwise, the date is variable and must be calculated. + ; ST.WDay contains the weekday and ST.Day the occurrence within ST.Month (5 = last) in this case. + If (ST.Year = 0) { + ST.Year := Year + ST.Day := TZI_GetWDayInMonth(ST.Year, ST.Month, ST.WDay, ST.Day) + } + + R.StandardDate := ST.TimeStamp + FormatTime, yd, % ST.TimeStamp, Yday + R.StandardDateYday := yd + R.StandardBias := NumGet(TZI, 84, "Int") + R.DaylightName := StrGet(&TZI + 88, 32, "UTF-16") + ST := New TZI_SYSTEMTIME(&TZI + 152) ; Calculate DaylightDate TimeStamp + If (ST.Year = 0) { + ST.Year := Year + ST.Day := TZI_GetWDayInMonth(ST.Year, ST.Month, ST.WDay, ST.Day) + } + R.DaylightDate := ST.TimeStamp + FormatTime, yd, % ST.TimeStamp, Yday + R.DaylightDateYday := yd + R.DaylightBias := NumGet(TZI, 168, "Int") + ; Calculate the UTC values for StandardDate and DaylightDate + UTCBias := R.Bias + R.DaylightBias ; StandardDate + UTCDate := R.StandardDate + UTCDate += UTCBias, M + R.StandardDateUTC := UTCDate + UTCBias := R.Bias + R.StandardBias ; DaylightDate + UTCDate := R.DaylightDate + UTCDate += UTCBias, M + R.DaylightDateUTC := UTCDate + R.TotalCurrentBias := isinRange(A_YDay, R.DaylightDateYday, R.StandardDateYday) ? R.Bias + R.DaylightBias + R.StandardBias : R.Bias + R.StandardBias + ; ToolTip, % R.TotalCurrentBias "`n" R.StandardDateYday "==" R.StandardDate "`n" R.DaylightDateYday "==" R.DaylightDateUTC "`n" R.StandardName "=" NumGet(TZI, 84, "Int") "==" NumGet(TZI, 168, "Int") , , , 2 + Return R +} + +TZI_GetWDayInMonth(Year, Month, WDay, Occurence) { + YearMonth := Format("{:04}{:02}01", Year, Month) ; bugfix + If YearMonth Is Not Date + Return 0 + If WDay Not Between 1 And 7 + Return 0 + If Occurence Not Between 1 And 5 ; 5 = last occurence + Return 0 + FormatTime, WD, %YearMonth%, WDay + While (WD <> WDay) { + YearMonth += 1, D + FormatTime, WD, %YearMonth%, WDay + } + While (A_Index <= Occurence) && (SubStr(YearMonth, 5, 2) = Month) { + Day := SubStr(YearMonth, 7, 2) + YearMonth += 7, D + } + Return Day +} +; ---------------------------------------------------------------------------------------------------------------------------------- +Class TZI_SYSTEMTIME { + __New(Pointer) { ; a pointer to a SYSTEMTIME structure + This.Year := NumGet(Pointer + 0, "Short") + This.Month := NumGet(Pointer + 2, "Short") + This.WDay := NumGet(Pointer + 4, "Short") + 1 ; DayOfWeek is 0 (Sunday) thru 6 (Saturday) in the SYSTEMTIME structure + This.Day := NumGet(Pointer + 6, "Short") + This.Hour := NumGet(Pointer + 8, "Short") + This.Min := NumGet(Pointer + 10, "Short") + This.Sec := NumGet(Pointer + 12, "Short") + This.MSec := NumGet(Pointer + 14, "Short") + } + TimeStamp[] { ; TimeStamp YYYYMMDDHH24MISS + Get { + Return Format("{:04}{:02}{:02}{:02}{:02}{:02}", This.Year, This.Month, This.Day, This.Hour, This.Min, This.Sec) + } + Set { + Return "" + } + } +} + +MoonPhaseCalculator(t:=0, calcDetails:=0) { +; Calculate the phase and position of the moon for a given date. +; The algorithm is simple and adequate for many purposes. +; +; This software was originally adapted to Javascript by Stephen R. Schmitt +; from a BASIC program from the 'Astronomical Computing' column of Sky & Telescope, +; April 1994, page 86, written by Bradley E. Schaefer. +; +; Subsequently adapted from Stephen R. Schmitt's Javascript to C++ for the Arduino +; by Cyrus Rahman. And further down the timeline, the C++ code was converted to AHK +; by Marius Șucan in September 2022. +; +; This work is/was subjected to Stephen Schmitt's copyright: +; Copyright 2004 Stephen R. Schmitt +; You may use or modify this source code in any way you find useful, provided +; that you agree that the author(s) have no warranty, obligations or liability. You +; must determine the suitability of this source code for your use. +; +; source https://github.com/signetica/MoonPhase + + Static MOON_SYNODIC_PERIOD := 29.530588853 ; Period of moon cycle in days. + , MOON_SYNODIC_OFFSET := 2451550.26 ; Reference cycle offset in days. From number of days since new moon on Julian date MOON_SYNODIC_OFFSET (18:15 UTC January 6, 2000), determine remainder of incomplete cycle. + , MOON_DISTANCE_PERIOD := 27.55454988 ; Period of distance oscillation + , MOON_DISTANCE_OFFSET := 2451562.2 + , MOON_LATITUDE_PERIOD := 27.212220817 ; Latitude oscillation + , MOON_LATITUDE_OFFSET := 2451565.2 + , MOON_LONGITUDE_PERIOD := 27.321582241 ; Longitude oscillation + , MOON_LONGITUDE_OFFSET := 2451555.8 + , JULIAN_UNIX_EPOCH := 2440587.5 ; The Unix epoch (zero-point) is January 1, 1970 GMT as Julian daye + , SECONDS_PER_DAY := 86400.0 + , LEAP_SECONDS := 27 ; since 1972 until 2022 + , M_PI := 3.14159265358979 + , phaseNames := {1:"New moon", 2:"Waxing Crescent", 3:"First Quarter" + , 4: "Waxing Gibbous", 5:"Full moon", 6:"Waning Gibbous" + , 7:"Last Quarter", 8:"Waning Crescent"} + + If (t="now" || !t) + t := A_NowUTC + + ; MsgBox, % NowUTC + t -= 19700101000000, S + + ; jDate := getJulianDate(t) + ; jDate := (t - LEAP_SECONDS) / SECONDS_PER_DAY + JULIAN_UNIX_EPOCH ; Julian day from Unix time + jDate := SM_Add(SM_Divide(SM_Add(t, -LEAP_SECONDS), SECONDS_PER_DAY), JULIAN_UNIX_EPOCH) ; Julian day from Unix time + + ; Calculate illumination (synodic) phase + phase := SM_Divide(SM_Add(jDate, -MOON_SYNODIC_OFFSET), MOON_SYNODIC_PERIOD) + ; phase := (jDate - MOON_SYNODIC_OFFSET) / MOON_SYNODIC_PERIOD + ; phase := phase - floor(phase) + phase := SM_Add(phase, - SM_Floor(phase)) + + ; Calculate age and illumination fraction. + age := phase * MOON_SYNODIC_PERIOD + ; age := SM_Multiply(phase, MOON_SYNODIC_PERIOD) + fraction := (1.0 - cos(2 * M_PI * phase)) * 0.5 + ; fraction := SM_Multiply(SM_Add(1.0, -cos(SM_Multiply(2, SM_Multiply(M_PI, phase) ) ) ), 0.5) + ; phaseID := mod(round(floor(phase * 8) + 0.51), 8) + 1 + + If (age<1.307) + phaseID := 1 + Else If (age<6.382) + phaseID := 2 + Else If (age<8.382) + phaseID := 3 + Else If (age<13.565) + phaseID := 4 + Else If (age<15.965) + phaseID := 5 + Else If (age<21.148) + phaseID := 6 + Else If (age<23.148) + phaseID := 7 + Else If (age<28.215) + phaseID := 8 + Else + phaseID := 1 + + phaseName := phaseNames[phaseID] + If (fraction>0.994 && phaseID=5) + phaseName .= " (peak)" + Else if (fraction<0.006 && phaseID=1) + phaseName .= " (peak)" + + If (calcDetails=1) + { + ; Calculate distance from anomalistic phase. + distancePhase := (jDate - MOON_DISTANCE_OFFSET) / MOON_DISTANCE_PERIOD + distancePhase := distancePhase - floor(distancePhase) + distance := 60.4 - 3.3 * cos(2 * M_PI * distancePhase) - 0.6 * cos(2 * 2 * M_PI * phase - 2 * M_PI * distancePhase) - 0.5 * cos(2 * 2 * M_PI * phase) + + ; Calculate ecliptic latitude from nodal (draconic) phase. + latPhase := (jDate - MOON_LATITUDE_OFFSET) / MOON_LATITUDE_PERIOD + latPhase := latPhase - floor(latPhase) + latitude := 5.1 * sin(2 * M_PI * latPhase) + + ; Calculate ecliptic longitude from sidereal motion. + longPhase := (jDate - MOON_LONGITUDE_OFFSET) / MOON_LONGITUDE_PERIOD + longPhase := longPhase - floor(longPhase) + longitude := longitude - 360 * longPhase + 6.3 * sin(2 * M_PI * distancePhase) + 1.3 * sin(2 * 2 * M_PI * phase - 2 * M_PI * distancePhase) + 0.7 * sin(2 * 2 * M_PI * phase) + if (longitude > 360) + longitude := longitude - 360 + } + ; fnOutputDebug("jd=" jDate "; phase=" phase "; fraction=" fraction "; " phaseName) + Return [phaseName, phaseID, phase, fraction, age, distance, latitude, longitude] } MixARGB(color1, color2, t := 0.5, gamma := 1) { diff --git a/lib/analog-clock-display.ahk b/lib/analog-clock-display.ahk index c034b81..e29b177 100644 --- a/lib/analog-clock-display.ahk +++ b/lib/analog-clock-display.ahk @@ -179,67 +179,55 @@ UpdateEverySecond() { ; draw moon phase If (analogMoonPhases=1) { - moonPhase := MoonPhaseCalculator(A_Year, A_Mon, A_MDay) - moonPhaseF := Round(moonPhase[2]) + moonPhase := MoonPhaseCalculator() + o_moonCycle := Round(moonPhase[3], 3) darkFace := mixARGB("0xFF" faceElements, "0xFF" faceBgrColor, 0.4) - brightFace := "0xEE" faceBgrColor - Diameter := Round(ClockDiameter*0.18, 2) - If (moonPhaseF=0 || moonPhaseF=4) - { - pBrush := (moonPhaseF=0) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - Diameter := Round(ClockDiameter*0.19, 2) - Gdip_FillEllipse(globalG, pBrush, CenterX-(Diameter//2), CenterY + diameter//2, Diameter, Diameter) - Gdip_DeleteBrush(pBrush) - } Else If (moonPhaseF=2 || moonPhaseF=6) - { - Diameter := Round(ClockDiameter*0.2, 2) - pBrush := (moonPhaseF=2) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - Gdip_FillEllipse(globalG, pBrush, CenterX-(Diameter//2), CenterY + diameter//2.1, Diameter, Diameter) - Gdip_DeleteBrush(pBrush) - - offsetuC := Diameter - Gdip_SetClipRect(globalG, CenterX - Diameter//2 + offsetuC*0.5, CenterY + diameter//2.1, Diameter, Diameter) - pBrush := (moonPhaseF=6) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - Gdip_FillEllipse(globalG, pBrush, CenterX-(Diameter//2), CenterY + diameter//2.1, Diameter, Diameter) - Gdip_DeleteBrush(pBrush) - Gdip_ResetClip(globalG) - } Else If (moonPhaseF=1 || moonPhaseF=5) - { - pBrushA := (moonPhaseF=5) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - pBrushB := (moonPhaseF=1) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - offsetuC := Diameter - DiameterZ := Round(ClockDiameter*0.20, 2) - Gdip_FillEllipse(globalG, pBrushB, CenterX - (DiameterZ/2), CenterY + DiameterZ/2.08, DiameterZ, DiameterZ) - Gdip_SetClipRect(globalG, CenterX - Diameter/2 + offsetuC*0.5, CenterY + diameter/2.58, Diameter, Diameter*1.25) - Diameter := Round(ClockDiameter*0.20, 2) - Gdip_FillEllipse(globalG, pBrushA, CenterX-(Diameter/2), CenterY + diameter/2.08, Diameter, Diameter) - Gdip_DeleteBrush(pBrushA) - - ; Gdip_SetClipRect(globalG, CenterX - Diameter//2 + offsetuC*0.3, CenterY + diameter//1.81, Diameter, Diameter, 1) - Gdip_FillEllipse(globalG, pBrushB, CenterX - (Diameter/1.4), CenterY + diameter/2.18, Diameter, Diameter) - Gdip_DeleteBrush(pBrushB) - Gdip_ResetClip(globalG) - } Else If (moonPhaseF=3 || moonPhaseF=7) + brightFace := "0xFF" faceBgrColor + + ; Static o_moonCycle := 0 + ; o_moonCycle += 0.05 + ; If (o_moonCycle>1) + ; o_moonCycle := 0 + + moonCycle := (o_moonCycle<0.5) ? o_moonCycle * 2 : 1 - (o_moonCycle - 0.5)*2 + If (o_moonCycle>=0.75) + flap := 2 + Else If (o_moonCycle>=0.5) + flap := 1 + + If (moonCycle>=0.5 && flap!=2) { - pBrushA := (moonPhaseF=3) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - pBrushB := (moonPhaseF=7) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) - offsetuC := Diameter - DiameterZ := Round(ClockDiameter*0.20, 2) - Gdip_FillEllipse(globalG, pBrushB, CenterX - (DiameterZ/2), CenterY + DiameterZ/2.08, DiameterZ, DiameterZ) - Gdip_SetClipRect(globalG, CenterX - Diameter, CenterY + diameter/2.58, Diameter, Diameter*1.25) - Diameter := Round(ClockDiameter*0.20, 2) - Gdip_FillEllipse(globalG, pBrushA, CenterX-(Diameter/2), CenterY + diameter/2.08, Diameter, Diameter) - Gdip_DeleteBrush(pBrushA) - - ; Gdip_SetClipRect(globalG, CenterX - Diameter//2 + offsetuC*0.3, CenterY + diameter//1.81, Diameter, Diameter, 1) - Gdip_FillEllipse(globalG, pBrushB, CenterX - (Diameter/3.4), CenterY + diameter/2.18, Diameter, Diameter) - Gdip_DeleteBrush(pBrushB) - Gdip_ResetClip(globalG) + flip := 1 + moonCycle -= 0.50001 } + bDark := (flip!=1) ? Gdip_BrushCreateSolid(darkFace) : Gdip_BrushCreateSolid(brightFace) + bBright := (flip!=1) ? Gdip_BrushCreateSolid(brightFace) : Gdip_BrushCreateSolid(darkFace) + Diameter := Round(ClockDiameter*0.20, 2) + Gdip_FillEllipse(globalG, bBright, CenterX-(Diameter/2), CenterY + diameter/2.18, Diameter, Diameter) + pPath := Gdip_CreatePath() + Gdip_AddPathEllipse(pPath, CenterX-(Diameter/2), CenterY + diameter/2.18, Diameter, Diameter) + Gdip_SetClipPath(globalG, pPath) + DiameterZ := (flip=1) ? Diameter*(moonCycle*2) : Diameter*(1 - moonCycle*2) + ; DiameterZ := (moonCycle<0.5) ? Diameter*(1 - moonCycle*2) : Diameter*(moonCycle/1.25) + If (flap=2) + Gdip_FillRectangle(globalG, bDark, CenterX, CenterY + diameter/2.18, Diameter//2, Diameter) + Else If (flap=1) + Gdip_FillRectangle(globalG, bDark, CenterX - diameter/2, CenterY + diameter/2.18, Diameter//2, Diameter) + Else If (moonCycle<0.5 && flip!=1) + Gdip_FillRectangle(globalG, bDark, CenterX - Diameter/2, CenterY + diameter/2.18, Diameter//2, Diameter) + Else + Gdip_FillRectangle(globalG, bDark, CenterX, CenterY + diameter/2.18, Diameter//2, Diameter) + + Gdip_FillEllipse(globalG, bDark, CenterX - (DiameterZ/2), CenterY + diameter/2.18, DiameterZ, Diameter) + Gdip_DeleteBrush(bBright) + Gdip_DeleteBrush(bDark) + Gdip_ResetClip(globalG) + Gdip_DeletePath(pPath) + Diameter := Round(ClockDiameter*0.20, 2) - pPen := Gdip_CreatePen("0xFF" faceElements, Round((ClockDiameter/100)*1.3, 2)) - Gdip_DrawEllipse(globalG, pPen, CenterX-(Diameter//2), CenterY + diameter//2.25,Diameter, Diameter) + pPen := Gdip_CreatePen("0x66" faceElements, Round((ClockDiameter/100)*1.3, 2)) + Gdip_DrawEllipse(globalG, pPen, CenterX - (Diameter/2), CenterY + diameter/2.18,Diameter, Diameter) Gdip_DeletePen(pPen) } @@ -373,11 +361,14 @@ ClockGuiGuiContextMenu(GuiHwnd, CtrlHwnd, EventInfo, IsRightClick, X, Y) { menuGenerated := 1 } + pk := MoonPhaseCalculator() Menu, ClockSizesMenu, Check, %analogDisplayScale%x Menu, ContextMenu, Add, Sc&ale, :ClockSizesMenu Menu, ContextMenu, Add, Menu, ContextMenu, Add, &Hide the clock, toggleAnalogClock Menu, ContextMenu, Add, Show &moon phases, toggleMoonPhasesAnalog + Menu, ContextMenu, Add, % pk[1], dummy + Menu, ContextMenu, Disable, % pk[1] If (analogMoonPhases=1) Menu, ContextMenu, Check, Show &moon phases @@ -387,12 +378,17 @@ ClockGuiGuiContextMenu(GuiHwnd, CtrlHwnd, EventInfo, IsRightClick, X, Y) { Menu, ContextMenu, Add, &Tick/tock sounds, ToggleTickTock If (tickTockNoise=1) Menu, ContextMenu, Check, &Tick/tock sounds + Menu, ContextMenu, Add, + Menu, ContextMenu, Add, Set &alarm or timer, PanelSetAlarm + Menu, ContextMenu, Add, Stop&watch, PanelStopWatch Menu, ContextMenu, Add, &Settings, ShowSettings - Menu, ContextMenu, Add, &About, AboutWindow + Menu, ContextMenu, Add, + Menu, ContextMenu, Add, &About, PanelAboutWindow } Menu, ContextMenu, Add - Menu, ContextMenu, Add, Close menu, dummy + Menu, ContextMenu, Add, Restart app, ReloadScript + ; Menu, ContextMenu, Add, Close menu, dummy Menu, ContextMenu, Show lastInvoked := A_TickCount Return diff --git a/lib/maths.ahk b/lib/maths.ahk new file mode 100644 index 0000000..856592e --- /dev/null +++ b/lib/maths.ahk @@ -0,0 +1,1559 @@ +/* +Scientific MATHS LIBRARY ( Filename = Maths.ahk ) +by Avi Aryan v3.43 +Thanks to hd0202, smorgasbord, Uberi and sinkfaze +Special thanks to smorgasbord for the factorial function +------------------------------------------------------------------------------ +DOCUMENTATION - http://avi-aryan.github.io/ahk/functions/smaths.html +Math-Functions.ahk - https://github.com/avi-aryan/Avis-Autohotkey-Repo/blob/master/Functions/Math-Functions.ahk +############################################################################## +FUNCTIONS +############################################################################## +* NOTES ARE PROVIDED WITH EACH FUNCTION IN THE FORM OF COMMENTS. EXPLORE +* SM_Solve(Expression, AHK=false) --- Solves a Mathematical expression. (with extreme capabilites) +* SM_Add(number1, number2) --- +/- massive numbers . Supports Real Nos (Everything) +* SM_Multiply(number1, number2) --- multiply two massive numbers . Supports everything +* SM_Divide(Dividend, Divisor, length) --- Divide two massive numbers . Supports everything . length is number of decimals smartly rounded. +* SM_Greater(number1, number2, trueforequal=false) --- compare two massive numbers +* SM_Prefect(number) --- convert a number to most suitable form. like ( 002 to 2 ) and ( 000.5600 to 0.56 ) +* SM_fact(number) --- factorial of a number . supports large numbers +* SM_toExp(number, decimals) --- Converts a number to Scientific notation format +* SM_FromExp(sci_num) --- Converts a scientific type formatted number to a real number +* SM_Pow(number, power) --- power of a number . supports large numbers and powers +* SM_Mod(Dividend, Divisor) --- Mod() . Supports large numbers +* SM_Round(number, decimals) --- Round() . Large numbers +* SM_Floor(number) --- Floor() . large numbers +* SM_Ceil(number) --- Ceil() . large number +* SM_e(N, auto=1) --- returns e to the power N . Recommend auto=1 for speed +* SM_Number2base(N, base) --- Converts N to base 'base' +* SM_Base2Number(H, base) --- Converts H in base 'base' to a real number +* SM_UniquePmt(pattern, ID, Delimiter=",") ;gives the unique permutation possible . +################################################################################ +READ +################################################################################ +* Pass the numbers as strings in each of these functions. This is done to avoid number trimming due to Internal AHK Limit +* For a collection of general Math functions, see < Math-functions.ahk > +*/ + +;msgbox % SM_Solve("%sin(1.59)% e %log(1000)%") ;is equal to sin(1.59) e log(1000) = 999.816 +;msgbox % SM_Solve("4 + ( 2*( 3+(4-2)*round(2.5) ) ) + (5c2)**(4c3)") +;msgbox % "The gravity on earth is: " SM_Solve("(6.67e-11 * 5.978e24) / 6.378e6^2") +;msgbox % Sm_fact(40) ;<--try puttin one more zero here +;msgbox,% SM_Mod( SM_Pow(3,77), 79) +;msgbox,% SM_Round("124389438943894389430909430438098232323.427239238023823923984",4) +;msgbox,% SM_ToExp("328923823982398239283923.238239238923", 3) +;msgbox,% SM_Divide("43.034934034904334", "89.3467436743", 10) +;msgbox,% SM_UniquePmt("abcdefghijklmnopqrstuvwxyz0123456789",12367679898956098) +;msgbox,% SM_Mod("-22","-7") +;msgbox % SM_fromexp("6.45423e10") +;msgbox,% SM_Divide("48.45","19.45",2) +;msgbox,% SM_UniquePmt("avi,annat,koiaur,aurkoi") +;msgbox,% SM_Solve("(28*45) - (45*28)") +;msgbox,% SM_Add("1280232382372012010120325634", "-12803491201290121201212.98") +;MsgBox,% SM_Solve("23898239238923.2382398923 + 2378237238.238239 - (989939.9939 * 892398293823)") +;msgbox,% SM_ToExp("0.1004354545") + +;var = sqrt(10!) - ( 2**5 + 5*8 ) +;msgbox,% SM_Solve(var) + +;Msgbox,% SM_Greater(18.789, 187) +;msgbox,% SM_Divide("434343455677690909087534208967834434444.5656", "8989998989898909090909009909090909090908656454520", 100) +;MsgBox,% SM_Multiply("111111111111111111111111111111111111111111.111","55555555555555555555555555555555555555555555.555") +;MsgBox,% SM_Prefect("00.002000") +;msgbox % t:=SM_Number2Base("10485761048", 2) ;base 2 +;msgbox % f:=SM_Number2base("10485761048", 32) ;base 32 +;msgbox % SM_Base2Number(t, 2) "`n" SM_Base2Number(f, 32) +;return + +;################################################################################################################################################################### + +;#Include, Maths.ahk + +/* +SM_Solve(expression, ahk=false) +Solves the expression in string. SM_Solve() uses the powerful functions present in the library for processing +ahk = true will make SM_Solve() use Ahk's +-/* for processing. Will be faster +* You can use global variables in expressions . To make SM_Solve see them as global vars, surround them by %..% +* To nest expressions with brackets , you can use the obvious ( ) brackets +* You can use numbers in sci notation directly in this function . ("6.67e-11 * 4.23223e24") +* You can use ! to calulate factorial ( 48! ) ( log(1000)! ) +* You can use ^ or ** to calculate power ( 2.2321^12 ) ( 4**14 ) +* You can use p or c for permutation or combination +* Use %...% to use functions with e, c, p . ("4**sin(3.14) + 5c%log(100)% + %sin(1.59)%e%log(1000)% + log(1000)!") +Example + global someglobalvar := 26 + msgbox,% SM_Solve("Sqrt(%someglobalvar%) * 4! * log(100) * ( 3.43e3 - 2^5 )") +*/ + +SM_Solve(expression, ahk=false){ +static fchars := "e- e+ **- ** **+ ^- ^+ + - * / \" , rchars := "#< #> ^< ^> ^> ^< ^> ¢ ¤ ¥ ¦ ¦" +;Reject invalid +if expression= + return + +;Check Expression for invalid +if expression is alpha +{ + temp2 := %expression% + return %temp2% ;return value of expression if it is a global variable or nothing +} +else if expression is number +{ + if !Instr(expression, "e") + return expression +} + + +;Fix Expression +StringReplace,expression,expression,%A_space%,,All +StringReplace,expression,expression,%A_tab%,,All +expression := SM_Fixexpression(expression) + +; Solving Brackets first +while b_pos := RegexMatch(expression, "i)[\+\-\*\\\/\^]\(") +{ + b_count := {"(": 1, ")": 0} + b_temp := Substr(expression, b_pos+2) + loop, parse, b_temp + { + b_count[A_LoopField] += 1 + if b_count["("] = b_count[")"] + { + end_pos := A_index + break + } + } + expression := Substr(expression, 1, b_pos) SM_Solve( Substr(expression, b_pos+2, end_pos-1) ) Substr(expression, end_pos+b_pos+2) +} +;Changing +,-,e-,e+ and all signs to different things +expression := SM_FixExpression(expression) ;FIX again after solving brackets + +loop, +{ + if !(Instr(expression, "(")){ + expression := SM_PowerReplace(expression, fchars, rchars, "All") ;power replaces replaces those characters + reserve .= expression + break + } + temp := Substr(expression, 1, Instr(expression, "(")) ;till 4+2 + sin( + temp := SM_PowerReplace(temp, fchars, rchars, "All") ;we dont want to replace +- inside functions + temp2 := SubStr(expression, Instr(expression, "(") + 1, Instr(expression, ")") - Instr(expression, "(")) + reserve .= temp . temp2 + expression := Substr(expression,Instr(expression, ")")+ 1) +} +; +expression := reserve +; The final solving will be done now +loop, parse, expression,¢¤¥¦ +{ + +;Check for functions -- + if RegExMatch(A_LoopField, "iU)^[a-z0-9_]+\(.*\)$") ;Ungreedy ensures throwing cases like sin(45)^sin(95) + { + fname := Substr(A_LoopField, 1, Instr(A_loopfield,"(") - 1) ;extract func + ffeed := Substr(A_loopfield, Instr(A_loopfield, "(") + 1, Instr(A_loopfield, ")") - Instr(A_loopfield, "(") - 1) ;extract func feed + loop, parse, ffeed,`, + { + StringReplace,feed,A_loopfield,",,All + feed%A_index% := SM_Solve(feed) + totalfeeds := A_index + } + + if fname = SM_toExp + outExp := 1 ; now output will be in Exp , set feed1 as the number + , number := feed1 + + else if totalfeeds = 1 + number := %fname%(feed1) + else if totalfeeds = 2 + number := %fname%(feed1, feed2) + else if totalfeeds = 3 + number := %fname%(feed1, feed2, feed3) + else if totalfeeds = 4 + number := %fname%(feed1, feed2, feed3, feed4) ;Add more like this if needed + + function := 1 + } + else + number := A_LoopField , function := 0 + +;Perform the previous assignment routine +if (char != "") { + ;The order is important here + if (!function) { + while match_pos := RegExMatch(number, "iU)%.*%", output_var) + output_var := Substr(output_var, 2 , -1) + , number := Substr(number, 1, match_pos-1) SM_Solve(Instr(output_var, "(") ? output_var : %output_var%) Substr(number, match_pos+Strlen(output_var)+2) + + if Instr(number, "#") or Instr(number, "^") + number := SM_PowerReplace(number, "#< #> ^> ^<", "e- e ^ ^-", "All") ;replace #,^ back to e and ^ + ;Symbols + ;As all use SM_Solve() , else-if is OK + if ( p := Instr(number, "c") ) or ( p := p + Instr(number, "p") ) ;permutation or combination + term_n := Substr(number, 1, p-1) , term_r := Substr(number,p+1) + , number := SM_Solve( term_n "!/" term_r "!" ( Instr(number, "c") ? "/(" term_n "-" term_r ")!" : "" ) ) + + else if Instr(number, "^") + number := SM_Pow( SM_Solve( SubStr(number, 1, posofpow := Instr(number, "^")-1 ) ) , SM_Solve( Substr(number, posofpow+2) ) ) + else if Instr(number, "!") + number := SM_fact( SM_Solve( Substr(number, 1, -1) ) ) + else if Instr(number, "e") ; solve e + number := SM_fromExp( number ) + } + + if (Ahk){ + if char = ¢ + solved := solved + (number) + else if char = ¤ + solved := solved - (number) + else if char = ¦ + { + if !number + return + solved := solved / (number) + } + else if char = ¥ + solved := solved * (number) + }else{ + + if char = ¢ + solved := SM_Add(solved, number) + else if char = ¤ + solved := SM_Add(solved,"-" . number) + else if char = ¦ + { + if !number + return + solved := SM_Divide(solved, number) + } + else if char = ¥ + solved := SM_Multiply(solved, number) + } +} +if solved = + solved := number + +char := Substr(expression, Strlen(A_loopfield) + 1,1) +expression := Substr(expression, Strlen(A_LoopField) + 2) ;Everything except number and char + +} +return, outExp ? SM_ToExp( solved ) : SM_Prefect( solved ) +} + +;############################################################################################################################### + +/* +SM_Add(number1, number2, prefect=true) +Adds or subtracts 2 numbers +To subtract A and B , do like SM_Add(A, "-" B) i.e. append a minus +*/ + +SM_Add(number1, number2, prefect=true){ ;Dont set Prefect false, Just forget about it. +;Processing +IfInString,number2,-- + count := 2 +else IfInString,number2,- + count := 1 +else + count := 0 +IfInString,number1,- + count+=1 +; +n1 := number1 +n2 := number2 +StringReplace,number1,number1,-,,All +StringReplace,number2,number2,-,,All +;Decimals +dec1 := Instr(number1,".") ? StrLen(number1) - InStr(number1, ".") : 0 +dec2 := Instr(number2,".") ? StrLen(number2) - InStr(number2, ".") : 0 + +if (dec1 > dec2){ + dec := dec1 + loop,% (dec1 - dec2) + number2 .= "0" +} +else if (dec2 > dec1){ + dec := dec2 + loop,% (dec2 - dec1) + number1 .= "0" +} +else + dec := dec1 +StringReplace,number1,number1,. +StringReplace,number2,number2,. +;Processing +;Add zeros +if (Strlen(number1) >= StrLen(number2)){ + loop,% (Strlen(number1) - strlen(number2)) + number2 := "0" . number2 +} +else + loop,% (Strlen(number2) - strlen(number1)) + number1 := "0" . number1 + +n := strlen(number1) +; +if count not in 1,3 ;Add +{ +loop, +{ + digit := SubStr(number1,1 - A_Index, 1) + SubStr(number2, 1 - A_index, 1) + (carry ? 1 : 0) + + if (A_index == n){ + sum := digit . sum + break + } + + if (digit > 9){ + carry := true + digit := SubStr(digit, 0, 1) + } + else + carry := false + + sum := digit . sum + } + ;Giving sign + if (Instr(n2,"-") and Instr(n1, "-")) + sum := "-" . sum +} +;SUBTRACT ****************** +elsE +{ +;Compare numbers for suitable order +numbercompare := SM_Greater(number1, number2, true) +if !(numbercompare){ + mid := number2 + number2 := number1 + number1 := mid +} +loop, +{ + digit := SubStr(number1,1 - A_Index, 1) - SubStr(number2, 1 - A_index, 1) + (borrow ? -1 : 0) + + if (A_index == n){ + StringReplace,digit,digit,- + sum := digit . sum + break + } + + if Instr(digit, "-") + borrow:= true , digit := 10 + digit ;4 - 6 , then 14 - 6 = 10 + (-2) = 8 + else + borrow := false + + sum := digit sum + } + ;End of loop ;Giving Sign + ; + If InStr(n2,"--"){ + if (numbercompare) + sum := "-" . sum + }else If InStr(n2,"-"){ + if !(numbercompare) + sum := "-" . sum + }else IfInString,n1,- + if (numbercompare) + sum := "-" . sum +} +;End of Subtract - Sum +;End +if ((sum == "-")) ;Ltrim(sum, "0") == "" + sum := 0 +;Including Decimal +If (dec) + if (sum) + sum := SubStr(sum,1,StrLen(sum) - dec) . "." . SubStr(sum,1 - dec) +;Prefect +return, Prefect ? SM_Prefect(sum) : sum +} + +;################################################################################################################### + +/* +SM_Multiply(number1, number2) +Multiplies any two numbers +*/ + +SM_Multiply(number1, number2){ +;Getting Sign +positive := true +if Instr(number2, "-") + positive := false +if Instr(number1, "-") + positive := !positive +number1 := Substr(number1, Instr(number1, "-") ? 2 : 1) +number2 := Substr(number2, Instr(number2, "-") ? 2 : 1) +; Removing Dot +dec := InStr(number1,".") ? StrLen(number1) - InStr(number1, ".") : 0 +If n2dotpos := Instr(number2, ".") + dec := dec + StrLen(number2) - n2dotpos +StringReplace,number1,number1,. +StringReplace,number2,number2,. +; Multiplying +loop,% Strlen(number2) + number2temp .= Substr(number2, 1-A_Index, 1) +number2 := number2temp +;Reversing for suitable order +product := "0" +Loop,parse,number2 +{ +;Getting Individual letters +row := "0" +zeros := "" +if (A_loopfield) + loop,% (A_loopfield) + row := SM_Add(row, number1, 0) +else + loop,% (Strlen(number1) - 1) ;one zero is already 5 lines above + row .= "0" + +loop,% (A_index - 1) ;add suitable zeroes to end + zeros .= "0" +row .= zeros +product := SM_Add(product, row, false) +} +;Give Dots +if (dec){ + product := SubStr(product,1,StrLen(product) - dec) . "." . SubStr(product,1 - dec) + product := SM_Prefect(product) +} +;Give sign +if !(positive) + product := "-" . product +return, product +} + +;###################################################################################################################################### +/* +SM_Divide(number1, number2, length=10) +Divide any two numbers + length = defines the number of decimal places in the result + +*/ + +SM_Divide(number1, number2, length:=15){ +;Getting Sign +positive := true +if (Instr(number2, "-")) + positive := false +if (Instr(number1, "-")) + positive := !positive +StringReplace,number1,number1,- +StringReplace,number2,number2,- +;Perfect them +number1 := SM_Prefect(number1) , number2 := SM_Prefect(number2) + +;Cases +;if !number1 && !number2 +; return 1 +if !number2 ; return blank if denom is 0 + return + +;Remove Decimals +dec := 0 +if Instr(number1, ".") + dec := - (Strlen(number1) - Instr(number1, ".")) ;-ve as when the num is multiplied by 10, 10 is divided +if Instr(number2, ".") + dec := Strlen(number2) - Instr(number2, ".") + dec + 0 +StringReplace,number1,number1,. +StringReplace,number2,number2,. + +number1 := Ltrim(number1, "0") , number2 := Ltrim(number2, "0") +decimal := dec , num1 := number1 , num2 := number2 ;These wiil be used to handle point insertion + +n1 := Strlen(number1) , n2 := StrLen(number2) ;Stroring n1 & n2 as they will be used heavily below +;Widen number1 +loop,% n2 + length + number1 .= "0" +coveredlength := 0 , dec := dec - n2 - length , takeone := false , n1f := n1 + n2 + length +;Start +while(number1 != "") +{ + times := 0 , below := "" , lendivide := 0 , n1fromleft := (takeone) ? Substr(number1, 1, n2+1) : Substr(number1, 1, n2) + + if SM_Greater(n1fromleft, number2, true) + { + todivide := n1fromleft + loop, 10 + { + num2temp%A_index% := SM_Multiply(number2, A_index) + if !(SM_Greater(todivide, num2temp%A_index%, true)){ + lendivide := (takeone) ? n2 + 1 : n2 + times := A_index - 1 , below := num2temp%times% + break + } + } + res .= zeroes_r + } + else + { + todivide := SubStr(number1, 1, n2+1) ; :-P (takeone) will not be needed here + loop, 10 + { + num2temp%A_index% := SM_Multiply(number2, A_index) + if !(SM_Greater(todivide, num2temp%A_index%, true)){ + lendivide := n2 + 1 + times := A_index - 1 , below := num2temp%times% + break + } + } + if (coveredlength != 0) + res .= zeroes_r "0" + } + res .= times , coveredlength+=(lendivide - Strlen(remainder)) ;length of previous remainder will add to number1 and so is not counted + remainder := SM_Add(todivide, "-" below) + + if remainder = 0 + remainder := "" + number1 := remainder . Substr(number1, lendivide + 1) + + if SM_Greater("0", remainder, true) + { + zeroes_k := "" + loop,% Strlen(number1) + zeroes_k .= "0" + if (number1 == zeroes_k){ + StringTrimRight,number1,number1,1 + number1 := "1" . number1 + res := SM_Multiply(res, number1) + break + } + } + if times = 0 + break + + zeroes_r := "" , takeone := false + if (remainder == "") { + loop, + if (Instr(number1, "0") == 1) + zeroes_r .= "0" , number1 := Substr(number1, 2) , coveredlength+=1 + else + break + } + if (Strlen(remainder) == n2) + takeone := true + else + loop,% n2 - StrLen(remainder) - 1 + zeroes_r .= "0" +} +;Putting Decimal points" + +if (dec < 0) +{ + oldformat := A_formatfloat + SetFormat,float,0.16e + Divi := Substr(num1,1,15) / Substr(num2,1,15) ; answer in decimals + decimal := decimal + Strlen(Substr(num1,16)) - Strlen(Substr(num2,16)) + + if (Instr(divi,"-")) + decimal := decimal - Substr(divi,-1) + 1 + else + decimal := decimal + Substr(divi,-1) + 1 + + if (decimal > 0) + res := Substr(res, 1, decimal) . "." . Substr(res, decimal + 1) + else if (decimal < 0){ + loop,% Abs(decimal) + zeroes_e .= "0" + res := "0." zeroes_e res + } + else + res := "0." res + + SetFormat,float,%oldformat% +} +else +{ + num := "1" + loop,% dec + num .= "0" + res := SM_Multiply(SM_Prefect(res), num) +} +return, ( (positive) ? "" : "-" ) . SM_Round(SM_Prefect(res), decimal < 0 ? Abs(decimal)+length : length) +} + +;########################################################################################################################################## + +/* +SM_UniquePmt(series, ID="", Delimiter=",") +Powerful Permutation explorer function that uses an unique algorithm made by the author to give a unique sequence linked to a number. +For example, the word "abc" has 6 permutations . So, SM_UniquePmt("abc", 1) gives a different sequence, ("abc", 2) a different till ("abc", 6) +As the function is powered by the the specialist Mod, Division and Multiply functions, it can handle series larger series too. +Examples -- +msgbox,% SM_UniquePmt("abcd") ;leaving ID = "" gives all permutations +msgbox,% SM_UniquePmt("abcdefghijklmnopqrstuvwxyz123456789", 23322323323) ;<----- That's called huge numbers +*/ + +SM_UniquePmt(series, ID="", Delimiter=","){ + +if Instr(series, Delimiter) + loop, parse, series,%Delimiter% + item%A_index% := A_LoopField , last := lastbk := A_Index +else{ + loop, parse, series + item%A_index% := A_loopfield + last := lastbk := Strlen(series) , Delimiter := "" +} + +if (ID == "") ;Return all possible permutations +{ + fact := SM_fact(last) + loop,% fact + toreturn .= SM_UniquePmt(series, A_index) . "`n" + return, Rtrim(toreturn, "`n") +} + +posfactor := (SM_Mod(ID, last) == "0") ? last : SM_Mod(ID, last) +incfactor := (SM_Mod(ID, last) == "0") ? SM_Floor(SM_Divide(ID,last)) : SM_Floor(SM_Divide(ID,last)) + 1 + +loop,% last +{ + tempmod := SM_Mod(posfactor + incfactor - 1, last) ;should be faster + posfactor := (tempmod == "0") ? last : tempmod ;Extraction point + res .= item%posfactor% . Delimiter , item%posfactor% := "" + + loop,% lastbk + if (item%A_index% == "") + plus1 := A_index + 1 , item%A_index% := item%plus1% , item%plus1% := "" + + last-=1 + if (posfactor > last) + posfactor := 1 +} +return, Rtrim(res, Delimiter) +} + +;#################################################################################################################################### +/* +SM_Greater(number1, number2, trueforqual=false) +Evaluates to true if number1 > number2 +If the "trueforequal" param is true , the function will also evaluate to true if number1 = number2 +*/ + +SM_Greater(number1, number2, trueforequal=false){ + +IfInString,number2,- + IfNotInString,number1,- + return, true +IfInString,number1,- + IfNotInString,number2,- + return, false + +if (Instr(number1, "-") and Instr(number2, "-")) + bothminus := true +number1 := SM_Prefect(number1) , number2 := SM_Prefect(number2) +; Manage Decimals +dec1 := (Instr(number1,".")) ? ( StrLen(number1) - InStr(number1, ".") ) : (0) +dec2 := (Instr(number2,".")) ? ( StrLen(number2) - InStr(number2, ".") ) : (0) + +if (dec1 > dec2) + loop,% (dec1 - dec2) + number2 .= "0" +else if (dec2 > dec1) + loop,% (dec2 - dec1) + number1 .= "0" + +StringReplace,number1,number1,. +StringReplace,number2,number2,. +; Compare Lengths +if (Strlen(number1) > Strlen(number2)) + return,% (bothminus) ? (false) : (true) +else if (Strlen(number2) > Strlen(number1)) + return,% (bothminus) ? (true) : (false) +else ;The final way out +{ + stop := StrLen(number1) + loop, + { + if (SubStr(number1,A_Index, 1) > Substr(number2,A_index, 1)) + return bothminus ? 0 : 1 + else if (Substr(number2,A_index, 1) > SubStr(number1,A_Index, 1)) + return bothminus ? 1 : 0 + + if (a_index == stop) + return, (trueforequal) ? 1 : 0 + } +} + +} + +;######################################################################################################################################### +/* +SM_Prefect(number) +Converts any number to Perfect form i.e removes extra zeroes and adds reqd. ones. eg > SM_Prefect(000343453.4354500000) +*/ + +SM_Prefect(number){ +number .= "" ;convert to string if needed + +number := RTrim(number, "+-") +if (number="") + return 0 + +if Instr(number, "-") + number := Substr(number, 2) , negative := true + +if Instr(number, "."){ + number := Trim(number, "0") + if (Substr(number,1,1) == ".") ;if num like .6767 + number := "0" number + if (Substr(number, 0) == ".") ;like 456. + number := Substr(number, 1, -1) + return,% (negative) ? ("-" . number) : (number) +} ; Non-decimal below +else +{ + if Trim(number, "0") + return negative ? ("-" . Ltrim(number, "0")) : (Ltrim(number, "0")) + else + return 0 +} +} + +;########################################################################################################################################### +/* +SM_Mod(dividend, divisor) +Gives remanider when dividend is divided by divisor +*/ + +SM_Mod(dividend, divisor){ +;Signs +positive := true +if Instr(divisor, "-") + positive := false +if (Instr(dividend, "-")) + positive := !positive +dividend := Substr(dividend, Instr(dividend, "-") ? 2 : 1) , divisor := Substr(divisor, Instr(divisor, "-") ? 2 : 1) , Remainder := dividend + +;Calculate no of occurances +if SM_Greater(dividend, divisor, true){ + div := SM_Divide(dividend, divisor) + div := Instr(div, ".") ? SubStr(div, 1, Instr(div, ".") - 1) : 0 + + if ( div == "0" ) + Remainder := 0 + else + Remainder := SM_Add(dividend, "-" SM_Multiply(Divisor, div)) +} +return, ( (Positive or Remainder=0) ? "" : "-" ) . Remainder +} + +;############################################################################################################################################ +/* +SM_ToExp(number, decimals="") // SM_Exp +Gives exponential form of representing a number. +If decimals param is omitted , it is automatically detected. +? SM_Exp was the function's name in old versions and so a dummy function has been created +*/ + +SM_Exp(number, decimals=""){ + return SM_ToExp(number, decimals) +} + +SM_ToExp(number, decimals=""){ + + if (dec_pos := Instr(number, ".")) + { + number := SM_Prefect(number) , number := Substr(number, Instr(number, "0")=1 ? 2 : 1) + Loop, parse, number + { + if A_loopfield > 0 + break + tempnum .= A_LoopField + } + number := Substr(number, Strlen(tempnum)+1) , power := dec_pos-Strlen(tempnum)-2 + number2 := Substr(number, 2) + StringReplace,number2,number2,. + number := Substr(number, 1, 1) "." number2 + decimals := ( decimals="" or decimals>Strlen(number2) ) ? Strlen(number2) : decimals + return SM_Round(number, decimals) "e" power + } + else + { + number := SM_Prefect(number) , decimals := ( decimals="" or decimals>Strlen(Substr(number,2)) ) ? Strlen(Substr(number,2)) : decimals + return SM_Round( Substr(number, 1, 1) "." Substr(number, 2), decimals ) "e" Strlen(number)-1 + } +} + +/* +SM_FromExp(expnum) +Converts exponential form to number +*/ + +SM_FromExp(expnum){ + if !Instr(expnum, "e") + return expnum + n1 := Substr(expnum, 1, t := Instr(expnum, "e")-1) , n2 := Substr(expnum, t+2) + return SM_ShiftDecimal(n1, n2) +} + +;####################################################################################################################################### + +/* +SM_Round(number, decimals) +Rounds a infinitely sized number to given number of decimals +*/ + +SM_Round(number, decimals){ +if Instr(number,".") +{ + nofdecimals := StrLen(number) - ( Instr(number, ".") = 0 ? Strlen(number) : Instr(number, ".") ) + + if (nofdecimals > decimals) + { + secdigit := Substr(number, Instr(number,".")+decimals+1, 1) + if secdigit >= 5 + loop,% decimals-1 + zeroes .= "0" + number := SM_Add(Substr(number, 1, Instr(number, ".")+decimals), (secdigit >= 5) ? "0." zeroes "1" : "0") + } + else + { + loop,% decimals - nofdecimals + zeroes .= "0" + number .= zeroes + } + return, Rtrim(number, ".") +} +else + return, number +} + +;################################################################################################################################################### + +/* +SM_Floor(number) +Floor function with extended support. Refer to Ahk documentation for Floor() +*/ + +SM_Floor(number){ + number := SM_Prefect(number) + + if Instr(number, "-") + if Instr(number,".") + return, SM_Add(Substr(number, 1, Instr(number, ".") - 1), -1) + else + return, number + else + return, Instr(number, ".") ? Substr(number, 1, Instr(number, ".") - 1) : number +} + +;################################################################################################################################################## + +/* +SM_Ceil(number) +Ceil function with extended support. Refer to Ahk documentation for Ceil() +*/ + +SM_Ceil(number){ + + number := SM_Prefect(number) + if Instr(number, "-") + { + if Instr(number,".") + return, Substr(number, 1, Instr(number, ".") - 1) + else + return, number + } + else + return, Instr(number, ".") ? SM_Add( Substr(number, 1, Instr(number, ".") - 1), 1) : number +} + +;################################################################################################################################################# + +/* +SM_fact(number) +Gives factorial of number of any size. Try SM_fact(200) :-; +;--- Edit +Now SM_Fact() uses smorgasboard method for faster results + http://ahkscript.org/boards/viewtopic.php?f=22&t=176&p=4786#p4781 +*/ + +SM_fact(N){ + res := 1 , k := 1 , carry := 0 + + N -= 1 + loop % N + { + StringSplit, l_times, res + index := l_times0 + k := A_index + 1 + + Loop %index% + { + digit := k * l_times%index% + carry + if ( digit > 9 ) + { + carry := RegExReplace(digit, "(.*)(\d)", "$1") + digit := RegExReplace(digit, "(.*)(\d)", "$2") + } + else + carry := 0 + r := digit r + index -- + } + + if ( carry != 0 ) + final := carry r + else + final := r + + res := final + + digit := index := final := r = + r := "" + carry := 0 + } + + return final ? final : 1 +} + +/* +SM_Pow(number, power) +Gives the power of a number . Uses SM_Multiply() for the purpose +*/ + +SM_Pow(number, power){ + + if (power < 1) + { + if !power ;0 + return 1 + if power Between -1 and 1 + return number ** power + + power := -power , I := Floor(power) , D := Mod(power, 1) + + if Instr(number, "-") && D ;if number is - and power is - in decimals , it doesnt exist ... -4 ** -2.5 + return + + D_part := number ** D ;The power of decimal part + I_part := SM_Pow(number, I) ;Now I will always be >=1 . So it will fall in the below else part + + return SM_Prefect( SM_Divide(1, SM_Multiply(I_part, D_part)) ) + } + else + { + if power > 6 + { + sqrt_c := Floor(Sqrt(power)) + x_c := SM_Iterate(number, sqrt_c) , loopc := Floor(power/sqrt_c) + x_c_loop := SM_iterate(x_c, loopc) , remPow := power - (sqrt_c*loopc) + x_remPow := SM_iterate(number, remPow) + return SM_Multiply(x_c_loop, x_remPow) + } + else x_7_pow7 := 1 + + a := 1 + loop % Mod(power, 7) + a := SM_Multiply(number, a) + + return SM_Multiply(x_7_pow7, a) + } +} + +/* +SM_e(N, auto=1) + Gives the power of e to N + auto = 1 enables smart rounding for faster results + Call auto as false (0) for totally accurate results. (may be slow) +*/ + +SM_e(N, auto=1){ + static e := 2.71828182845905 , d := 14 ;rendering precise results with speed . + + if (N > 5) and auto + e := SM_Round("2.71828182845905", (F := d-N+5)>2 ? F : 2) + return SM_Pow(e, N) +} + +/* +SM_ base Conversion functions +via Base to Number and Number to Base conversion +Base = 16 for HexaDecimal , 2 for Binary, 8 for Octal and 10 for our own number system +*/ + +SM_Number2Base(N, base=16){ + + baseLen:=base<10 ? SM_Ceil((10/base)*Strlen(N)) : Strlen(N) + + if SM_checkformat(N) && SM_Checkformat(base**(baseLen-1)) ;check if N and base**base (used below) is compatitible + loop % baseLen + D:=Floor(N/(T:=base**(baseLen-A_index))),H.=!D?0:(D>9?Chr(D+87):D),N:=N-D*T + else + loop % baseLen + D:=SM_Floor( SM_Divide(N , T:= SM_Pow(base, baselen-A_index)) ) , H.=!D?0:(D>9?Chr(D+87):D) , N:=SM_Add( N, "-" SM_Multiply(D,T) ) + + return Ltrim(H,"0") +} + +SM_Base2Number(H, base=16){ + StringLower, H, H ;convert to lowercase for Asc to work + S:=Strlen(H),N:=0 + loop,parse,H + N := SM_Add( N, SM_Multiply( (A_LoopField*1="")?Asc(A_LoopField)-87:A_LoopField , SM_Pow(base, S-A_index) ) ) + return N +} + + +;################# NON - MATH FUNCTIONS ####################################### +;################# RESERVED ################################################### + +; Checks if n is within AHK range +SM_Checkformat(n){ + static ahk_ct := 9223372036854775807 + if n < 0 + return 0 + if ( ahk_ct > n+0 ) + return 1 +} + +;Shifts the decimal point +;specify - to shift in left direction + +SM_ShiftDecimal(number, dec_shift=0){ + + if Instr(number, "-") + number := Substr(number,2) , minus := 1 + dec_pos := Instr(number, ".") , numlen := StrLen(number) + + loop % Abs(dec_shift) ;create zeroes + zeroes .= "0" + if !dec_pos ;add decimal to integers + number .= ".0" + number := dec_shift>0 ? number zeroes : zeroes number ;append zeroes + + dec_pos := Instr(number, ".") ;get dec_pos in the new number + StringReplace, number, number, % "." + + number := Substr(number, 1, dec_pos+dec_shift-1) "." Substr(number, dec_pos+dec_shift) + return ( minus ? "-" : "" ) SM_Prefect(number) +} + +; powers a number n times +SM_Iterate(number, times){ + x := 1 + loop % times + x := SM_Multiply(x, number) + return x +} + +; fast string replace +SM_PowerReplace(input, find, replace, options="All"){ + StringSplit, rep, replace, % A_space + loop, parse, find, % A_Space + StringReplace, input, input, % A_LoopField, % rep%A_index%, % options + return Input +} + + +SM_FixExpression(expression){ +expression := Rtrim(expression, "+-=*/\^") +StringReplace,expression,expression,--,+,All +StringReplace,expression,expression,-+,-,All +StringReplace,expression,expression,+-,-,All +StringReplace,expression,expression,++,+,All + +;Reject invalid +if expression= + return + +;if (Substr(expression, 1, 1) != "+") or (Substr(expression, 1, 1) != "-") +if Substr(expression, 1, 1) == "-" + expression := "0" expression ;make it 0 - 10 +else expression := "+" expression + +loop, +{ +if Instr(expression, "*-"){ + fromleft := Substr(expression, 1, Instr(expression, "*-")) + StringGetPos,posplus,fromleft,+,R + StringGetPos,posminus,fromleft,-,R + if (posplus > posminus) + fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2) + else + fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2) + expression := fromleft . Substr(expression, Instr(expression, "*-") + 2) +}else if Instr(expression, "/-"){ + fromleft := Substr(expression, 1, Instr(expression, "/-")) + StringGetPos,posplus,fromleft,+,R + StringGetPos,posminus,fromleft,-,R + if (posplus > posminus) + fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2) + else + fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2) + expression := fromleft . Substr(expression, Instr(expression, "/-") + 2) +}else if Instr(expression, "\-"){ + fromleft := Substr(expression, 1, Instr(expression, "\-")) + StringGetPos,posplus,fromleft,+,R + StringGetPos,posminus,fromleft,-,R + if (posplus > posminus) + fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2) + else + fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2) + expression := fromleft . Substr(expression, Instr(expression, "\-") + 2) +}else if Instr(expression, "x-"){ + fromleft := Substr(expression, 1, Instr(expression, "x-")) + StringGetPos,posplus,fromleft,+,R + StringGetPos,posminus,fromleft,-,R + if (posplus > posminus) + fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2) + else + fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2) + expression := fromleft . Substr(expression, Instr(expression, "x-") + 2) +}else + break +} +StringReplace,expression,expression,--,+,All +StringReplace,expression,expression,-+,-,All +StringReplace,expression,expression,+-,-,All +StringReplace,expression,expression,++,+,All + +return, expression +} + + +;<------------------------------------------- BYE --------------------------------------------------------------------------------> + + +/* +++++++++++++++++++++++ +Math_Functions v0.13 + +----------------------- +by Avi Aryan + +++++++++++++++++++++++ + +Math_Functions is a collection of useful mathematical functions for general usage. + +++++++++++++++++++++++++++++ +CREDITS (Alphabetically) + +++++++++++++++++++++++++++++ +A v i +Lazzlo + +############################ +Scientific Maths (Maths.ahk) - https://github.com/Avi-Aryan/Avis-Autohotkey-Repo/blob/master/Functions/Maths.ahk +*/ + +/* +SolveQuadratic(x1, x2, a, b, c) // cubic(x1, x2, x3, a, b, c, d) BY Lazzlo + + x1 = Byref variable to store 1st root + x2 = Byref variable to store 2nd root + x3 = Byref variable to store 3rd root + + a = first coefficient in the eqn + ..... + d = fourth coefficient in the eqn + +Returns > + Returns the number of roots possible +*/ + +SolveQuadratic(ByRef x1, ByRef x2, a,b,c) { ; -> #real roots {x1,x2} of ax**2+bx+c + i := fcmp(b*b,4*a*c,63) ; 6 LS bit tolerance + If (i = -1) { + x1 := x2 := "" + Return 0 + } + If (i = 0) { + x1 := x2 := -b/2/a + Return 1 + } + d := sqrt(b*b - 4*a*c) + x1 := (-b-d)/2/a + x2 := x1 + d/a + Return 2 +} + +SolveCubic(ByRef x1, ByRef x2, ByRef x3, a,b,c,d) { ; -> #real roots {x1,x2,x3} of ax**3+bx**2+cx+d + Static pi23:=2.094395102393195492, pi43:=4.188790204786390985 + x := -b/3/a ; Nickalls method + y := ((a*x+b)*x+c)*x+d + E2:= (b*b-3*a*c)/9/a/a + H2:= 4*a*a*E2*E2*E2 + i := fcmp(y*y,H2, 63) + If (i = 1) { ; 1 real root + q := sqrt(y*y-H2) + x1 := x + SolveNthRoot((-y+q)/2/a, 3) + SolveNthRoot((-y-q)/2/a, 3) + x2 := x3 := "" + Return 1 + } + If (i = 0) { ; 3 real roots (1 or 2 different) + If (fcmp(H2,0, 63) = 0) { ; root1 is triple... + x1 := x2 := x3 := x + Return 1 + } ; h <> 0 : root2 is double... + E := SolveNthRoot(y/2/a, 3) ; with correct sign + x1 := x - E - E + x2 := x3 := x + E + Return 2 + } ; i = -1 : 3 real roots (different)... + t := acos(-y/sqrt(H2)) / 3 + E := 2*sqrt(E2) + x1 := x + E*cos(t) + x2 := x + E*cos(t+pi23) + x3 := x + E*cos(t+pi43) + Return 3 +} + +;################################################## + +/* +SolveRoots(expression) BY Avi Aryan + + expression = STRING containing CSV of coefficients in a polynomial + +Returns > + the Comma - separated roots of (expression) + +Notes > + * Requires Scientific Maths lib (Maths.ahk) . + * Not dependable at all as it uses a smart loop to find roots. + Use quadratic() and cubic() functions where they are possible. +*/ + +SolveRoots(expression){ ;Enter a, b, c for quad. eqn ------ a, b, c, d for cubic eqn. and so on + StringReplace,expression,expression,%A_space%,,All + StringReplace,expression,expression,%A_tab%,,All + ;eqn, limit + limit := 0 + loop, parse, expression,`, ;get individual coffs + { + if !(Instr(A_Loopfield, "+") or Instr(A_loopfield, "-")) + coff%A_index% := "+" A_loopfield + else + coff%A_index% := A_loopfield + + limit := limit + Abs(A_loopfield) , nofterms := A_index + } + + loop % (nofterms - 1) ;not including contsant + term .= Substr(coff%A_index%, 1, 1) "(" Substr(coff%A_index%,2) . " * SM_Pow(x, " . (nofterms - A_index) . ")" ")" + + term .= coff%nofterms% , plot := limit + + if (limit / (nofterms-1) < 8) ;if roots are within short range, slow down + speed := defaultspeed := 0.2 , incomfac := "0.00" , lessfac := "0.01" + else + speed := defaultspeed := 1 , incomfac := "0.0" , lessfac := "0.05" + + positive := true + StringReplace,expression,term,x,%plot%,All ;getting starting value + + if Instr(SM_Solve(expression, 1), "-") + positive := false + + while (plot >= -limit) ;My theorem - Safe Range + { + StringReplace,expression,term,x,%plot%,All + fx := SM_Solve(expression, true) ;Over here ... Uses the AHK processes for faster results + + if (speed == defaultspeed){ + if (fx == "0"){ + roots .= SM_Prefect(plot) . "," + positive := !positive , plot-=speed + if (Instr(roots, ",", false, 1, nofterms - 1)) ;if all roots have already been found, go out + break + continue + } + } + else{ + compare := Substr(Ltrim(fx, "-"),1,4) + if ((Instr(compare,incomfac) == 1) or compare+0 < lessfac+0) + { + roots .= SM_Prefect(plot) . "," + speed := defaultspeed , positive := !positive , plot-=speed + if (Instr(roots, ",", false, 1, nofterms - 1)) + break + continue + } + } + + if (positive){ + if (Instr(fx,"-")){ + plot+=defaultspeed , positive := !positive , speed := 0.01 ;Lower the value, more the time and accurateness + continue + } + }else{ + if !(Instr(fx, "-")){ + plot+=defaultspeed , positive := !positive , speed := 0.01 + continue + } + } + plot-=speed + } + return, Rtrim(roots, ",") +} + +;################################################## + +/* +SolveNthRoot(number, n) BY Avi Aryan + + number = The number whose root is to extracted + n = which root to be extracted + +Returns > + the (n)-th root of (number) +*/ + +SolveNthRoot(number, n){ + if Instr(number, "-") + { + number := Substr(number,2) + if !Mod(n, 2) ;check for even + return + sign := "-" + } + return sign . Round(number**(1/n)) +} + +;################################################## + +/* +dec2frac(number) by Avi Aryan + Converts decimal to fraction + +Returns > + space separated values of numerator and denominator +*/ + +dec2frac(number){ + if !( dec_pos := Instr(number, ".") ) + return number + + n_dec_digits := Strlen(number) - dec_pos , dec_num := Substr(number, dec_pos+1) + , base_num := Substr(number, 1, dec_pos-1) + + t := 1 + loop % n_dec_digits + t .= "0" + + numerator := base_num*t + dec_num , denominator := t + HCF := SolveGCD(numerator, denominator) + numerator /= HCF , denominator /= HCF + + return Round(numerator) " " Round(denominator) +} + +;################################################## + +/* +SolveGCD(a,b) BY Lazzlo + + a = first number + b = second number + +Returns > + the Greatest Common Divisor/Highest common factor of the two numbers +*/ + +SolveGCD(a,b) { + Return b=0 ? Abs(a) : SolveGCD(b, mod(a,b)) +} + +;################################################## + +/* +Antilog(number, base) BY Avi Aryan + + number = Number for which antilog is to be found + base = base to be used in the process + +Returns > + the antilog of number (number) calculated by using base (base) +*/ + +Antilog(number, basetouse:=10){ + oldformat := A_FormatFloat + SetFormat, float, 0.16 + + if (basetouse="e") + basetouse := 2.71828182845905 + else if (basetouse="pi") + basetouse := 3.14159265358979 + + toreturn := basetouse ** number ; why not use SM_Pow() ? + SetFormat, floatfast, %oldformat% + return, toreturn +} + +;################################################# + +/* +IsPrime(N) By Avi + + Returns 1 if the number is prime +*/ + +IsPrime(n) { ;by kon + if (n < 2) + return, 0 + else if (n < 4) + return, 1 + else if (!Mod(n, 2)) + return, 0 + else if (n < 9) + return 1 + else if (!Mod(n, 3)) + return, 0 + else { + r := Floor(Sqrt(n)) + f := 5 + while (f <= r) { + if (!Mod(n, f)) + return, 0 + if (!Mod(n, (f + 2))) + return, 0 + f += 6 + } + return, 1 + } +} + +;IsPrime(N){ +; if N in 2,3,5,7 +; return 1 +; else if !Mod(Lst := Substr(N, 0), 2) or (Lst = 5) or !Mod(N,3) or ( Mod(N-1, 6) && Mod(N+1, 6) ) +; return 0 + +; Frt := Floor( Floor(Sqrt(N)) / 10 ) + +; loop % Frt+1 +; { +; if !Mod(N, A_index*10-7) ;-10+3 +; return 0 +; if !Mod(N, A_index*10-3) ;-10+7 +; return 0 +; if !Mod(N, A_index*10-9) ;-10+1 +; if A_index >1 +; return 0 +; } +; return 1 +;} + + +;################################################## + +Choose(n,k) { ; Binomial coefficient BY Lazzlo + p := 1, i := 0, k := k < n-k ? k : n-k + Loop %k% ; Recursive (slower): Return k = 0 ? 1 : Choose(n-1,k-1)*n//k + p *= (n-i)/(k-i), i+=1 ; FOR INTEGERS: p *= n-i, p //= ++i + Return Round(p) +} + +;################################################## + +/* +FibonacciNthTerm(n) BY Lazzlo + n = nth term in fibonacci series + +Returns > + The (n)-th number in fibonacci series (The series starts from 1) +*/ + +FibonacciNthTerm(n) { ; n-th Fibonacci number (n < 0 OK, iterative to avoid globals) + a := 0, b := 1 + Loop % abs(n)-1 + c := b, b += a, a := c + Return n=0 ? 0 : n>0 || n&1 ? b : -b +} +;################################################## + +/* +SM_SimpleFactorial(n) BY Lazzlo + Also see Sm_fact() for any size. + +Returns > + The factorial of (n) +*/ + +SM_SimpleFactorial(n) { + Return (n<2) ? 1 : n * SM_SimpleFactorial(n-1) +} + +;################################################## + +/* +LogB(number, base) BY Avi Aryan + + number = number + base = base of log + +Returns > + Log of (number) to the base (base) +*/ + +LogB(number, base){ + if ( number >= 0 AND base > 0 ) + return Round(log(number) / log(base)) +} + +;################################################## + +/* +Trigometric_Functions(x) BY Lazzlo + + x = angle in radians + +Returns > + The corresponding Trignometric value +*/ + +cot(x) { ; cotangent + Return 1/tan(x) +} +acot(x) { ; inverse cotangent + Return 1.57079632679489662 - atan(x) +} +atan2(x,y) { ; 4-quadrant atan + Return dllcall("msvcrt\atan2","Double",y, "Double",x, "CDECL Double") +} + +sinh(x) { ; hyperbolic sine + Return dllcall("msvcrt\sinh", "Double",x, "CDECL Double") +} +cosh(x) { ; hyperbolic cosine + Return dllcall("msvcrt\cosh", "Double",x, "CDECL Double") +} +tanh(x) { ; hyperbolic tangent + Return dllcall("msvcrt\tanh", "Double",x, "CDECL Double") +} +coth(x) { ; hyperbolic cotangent + Return 1/dllcall("msvcrt\tanh", "Double",x, "CDECL Double") +} + +asinh(x) { ; inverse hyperbolic sine + Return ln(x + sqrt(x*x+1)) +} +acosh(x) { ; inverse hyperbolic cosine + Return ln(x + sqrt(x*x-1)) +} +atanh(x) { ; inverse hyperbolic tangent + Return 0.5*ln((1+x)/(1-x)) +} +acoth(x) { ; inverse hyperbolic cotangent + Return 0.5*ln((x+1)/(x-1)) +} + +;############################################################################################################################################################ + +fcmp(x,y,tol) { + Static f + If (f = "") { + VarSetCapacity(f,162) + Loop 324 + NumPut("0x" +. SubStr("558bec83e4f883ec148b5510538b5d0c85db568b7508578b7d148974241889542410b9000000807f" +. "137c0485f6730d33c02bc68bd91b5d0c89442418837d14007f137c0485d2730d33c02bc28bf91b7d1489442410" +. "8b7424182b7424108b45188bcb1bcff7d8993bd17f187c043bc677128b4518993bca7f0a7c043bf0770433c0eb" +. "183bdf7f117c0a8b44241039442418730583c8ffeb0333c0405f5e5b8be55dc3" +, 2*A_Index-1,2), f, A_Index-1, "Char") + } + Return DllCall(&f, "double",x, "double",y, "Int",tol, "CDECL Int") +} + + + diff --git a/sounds/howling.mp3 b/sounds/howling.mp3 new file mode 100644 index 0000000..2d9952d Binary files /dev/null and b/sounds/howling.mp3 differ