Notki oznaczone tagiem ‘Harmonogram zdarzeń’

Triki z PowerShellem #13 – Prędkość czasu

2009-12-31 13:47

Ostatni dzień roku to dobry moment na różne dziwne przemyślenia na temat czasu. Kiedyś z tej okazji wymyśliłem zupełnie nowy system kalendarza, a dzisiaj przypomniałem sobie o niezupełnie poważnym pomyśle autorstwa Rega, ze zbliżonej dziedziny.
Chodzi o oryginalną wielkość "fizyczną": prędkość czasu. Ma ona ilościowo mierzyć znany wszystkim fakt, że wrażenie upływającego czasu jest różne w różnych sytuacjach. Gdy w rzeczywistości upłynął pewien czas t, a nam wydawało się, że minął raczej czas t', to odczuwana przez nas prędkość czasu \tau wynosi

\displaystyle \tau = \frac{t}{t'}.

Dla przykładu: na nudnym wykładzie mogło minąć ledwie 15 minut, podczas gdy nam wydaje się, że siedzimy na nim już godzinę; wówczas \tau_1 = 0,25 / 1 = 0,25. Z kolei grając przez trzy godziny możemy mieć wrażenie, że upłynęło tylko 30 minut - wtedy \tau_2 = 3 / 0,5 = 6. Jak widać \tau_1 <\tau_2, zatem teoria zgadza się tutaj z intuicją, co pozwala wnioskować, że wielkość jest dobrze zdefiniowana :)

Pozostaje jeszcze kwestia jej pomiaru. W swoim oryginalnym artykule (który w tajemniczy sposób zniknął z sieci) Reg zaproponował, że można by go przeprowadzić za pomocą odpowiedniego programu. Miałby on działać w tle, losować pewien interwał czasu i po jego upływie pytać użytkownika, ile czasu według niego upłynęło od ostatniego pytania. Z dokładnością do małych błędów pomiarowych (np. czasu potrzebnego na wpisanie odpowiedzi) metoda wydaje się dobra - czemu więc by jej nie zaimplementować? :]
To właśnie uczyniłem, posługując się oczywiście swoim ulubionym narzędziem na takie okazje, czyli PowerShellem. Pewnym problemem było to, jak w skrypcie konsolowym postarać się o mierzenie czasu w sposób, który byłby niezauważalny dla użytkownika. Da się to jednak łatwo zrobić, posługując się... wbudowanym w system Harmonogramem zadań (Task Scheduler). Istnieje bowiem do niego dobrze udokumentowane, ładne i przejrzyste COM-owe API (dostępne od Visty wzwyż), którego użycie w PowerShellu wygląda zresztą kilka razy lepiej niż w C++ ;P
Wynikowy skrypt wygląda więc następująco:

# timespeed.ps1
# Skrypt do mierzenia prędkości czasu
param ([int]$minutes = 0)

# Stałe
$TASK_NAME = "TimeSpeed_Task"   # Nazwa zadania w Harmonogramie

# Pobieramy obiekt harmonogramu zadań
$ts = New-Object -ComObject Schedule.Service
$ts.Connect($null, $null, $null, $null)
$tf = $ts.GetFolder($(New-Object String @([char]92, 1))) # "\"

if ($minutes -eq 0)
{
    # Pierwsze uruchomienie
    $task = $ts.NewTask(0)
    $task.Data = ""
    $continue = "T"
}
else
{
    # Kolejne uruchomienia
    $task = $tf.GetTask($TASK_NAME).Definition
   
    # Pytamy użytkownika i liczymy prędkość czasu
    $userMinutes = Read-Host -Prompt "Liczba minut od ostatniego razu"
    $d_tau = $minutes / $userMinutes
    if (-not [String]::IsNullOrEmpty($task.Data))
    {
        $timeData = $task.Data.Split(',')
        $totalTime = [int]$timeData[0]
        $totalUserTime = [int]$timeData[1]
    }
    $totalTime += $minutes
    $totalUserTime += $userMinutes
    $tau = $totalTime / $totalUserTime
    $task.Data = $totalTime.ToString() + "," + $totalUserTime.ToString()
   
    # Wyświetlamy aktualne wyniki
    "Rzeczywista liczba minut: " + $minutes | Out-Host
    "Chwilowa prędkość czasu: " + $d_tau | Out-Host
    "Całkowita prędkość czasu: " + $tau | Out-Host
   
    # Pytamy użytkownika, czy chce kontynuować
    $continue = Read-Host -Prompt "Wykonać następny pomiar (T/n)?"
}

if ($continue -ine "n")
{
    # Losujemy nowy interwał czasowy (od 5 do 60 minut, co 5)
    $rand = New-Object System.Random
    $nextMinutes = ($rand.Next(0, 12) + 1) * 5
   
    # Dodajemy trigger dla zadania (czas: za X minut)
    $task.Triggers.Clear()
    $trigger = $task.Triggers.Create(1) # 1 - trigger na określony czas
    $nextTime = [DateTime]::Now.AddMinutes($nextMinutes)
    $trigger.StartBoundary = $nextTime.ToString("o")
   
    # Dodajemy akcję (uruchomienie skryptu)
    $task.Actions.Clear()
    $action = $task.Actions.Create(0)   # 0 - uruchomienie polecenia
    $action.Path = "powershell"
    $action.Arguments = "-Command . '" + $MyInvocation.MyCommand.Path
    $action.Arguments += "' -minutes " + $nextMinutes.ToString()
   
    # Dodajemy zadanie
    # (6 - stwórz lub uaktualnij)
    # (3 - zadanie uruchamiane tylko przy zalogowanym użytkowniku)
    $tf.RegisterTaskDefinition($TASK_NAME, $task, 6, $null, $null, 3) | Out-Null
}
else
{
    # Koniec - usuwamy zdarzenie
    try { $tf.DeleteTask($TASK_NAME, 0) } catch { }
}

Przy swoim pierwszym uruchomieniu tworzy on nowe zadanie w Harmonogramie, które polega na jego ponownym odpaleniu po upływie losowej liczby minut (5, 10, 15, itd. aż do maks. 60 minut). Wtedy użytkownik jest pytany o to, ile czasu według niego upłynęło, a następnie wyświetlają się częściowe wyniki pomiaru. Wówczas można zdecydować o jego kontynuowaniu lub zakończeniu. (Zawsze można też ręcznie usunąć zadanie z Harmonogramu, rzecz jasna).

Skrypt w PSh do mierzenia prędkości czasu

I to w sumie tyle. Można już przystąpić do badań określających dokładnie, jak bardzo dłuży nam się czas do północy :))

  • RSS
  • Facebook
  • Twitter
  • Wykop
  • Reddit
  • del.icio.us
  • Google Bookmarks
 



© 2010 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.