Before we go into how I report my observation sessions, it makese sense to know how I publish my blog. I do not use a memory or processor intensive blogging platform such as Word Press. Instead, my entire blog is made of static HTML files. No dynamic applications serving up data here, except for the web server itself of course!

Why do I do this?

  1. I consume less resources. Computing power these days are really sucking up major amounts of energy and for the most part, they do so for no good reason. I am not contibuting to this by my software choices, like what software my blog runs.
  2. It’s easier to use. When I want to create a new post, I just fire up my familiar text editor and type away. I then save my file under my blogs posts directory as something such as ‘2013-02-15_observation-reports-how-to.html’
  3. It’s ultra fast. No processing is really done to serve this page up. My webserver simply reads the page from disk and transfers it to you. Most systems require substantial amounts of processing just to show you a blog post. No so here.

How do I do this?

I use one of many static site generators. The generator I chose to use is PieCrust. All it requires is the command line version of PHP installed on the computer you wish to do your work on. OSX has everything you need already installed.

Once I add a new blog post, or run my export observation reports, all I do is run chef bake --root=jeremy.cowgar.com and all is done. For this blog, it takes my MacBook about 420ms (roughly 1/2 a second) to generate my blog from scratch. Normally I am only updating a page or adding a new post. It then takes less than 100ms (1/10th a second) to simply do an update.

How do I get my observation reports on my blog?

Finally, what you’ve come for! I use a program called AstroPlanner. It has the ability to be scripted. I simply wrote a script that loops through my observations creating static observation report files in the markdown format as if I would have typed it in myself. PieCrust then picks those files up and makes it a part of my blog.

I had thought of uploading my script to the nice user contribution section of AstroPlanner, but it is still in its infancy and I would like to see two things before I do this:

  1. That people will want to use it. If they do not, then I there is no reason for me to make it customizable for anyone to use as that just complicates the script for no reason (since no one wants to use it).
  2. That my script is good coding standards and is effective in its methods of accessing the data. My observation database is small. I do not know what this script will do for someone with a huge observation database.

So, until I get the above two questions answered, I will simply include the code here. Please note, that to use it you should change three lines in the main sub routine in the script. These lines define where the files should be written. Chances are you are not going to be writing your files to my home directory in a sub-directory named jeremy.cowgar.com!

Please feel free to send me an email, comment on this post or contact me on the AstroPlanner users group with any questions about the script.

//- Export observation data to a blog run by PieCrust or a similar
//- static site file generator capable of parsing Markdown.
//-
//- Each session will create a blog post that lists objects
//- observed during that session along with all associated
//- notes. An addition file will be created that will list
//- all objects observed in order of its ID stating simply
//- the last date it was observed.

//# Author: Jeremy Cowgar
//# E-Mail: (jeremy [AT] cowgar -DOT- com)
//# Category: Category|Hierarchy|Here
//# MinVersion: 2.0
//# Keywords: Blog, Observation, Export, Markdown
//# URL: http://jeremy.cowgar.com

function observationFilename(baseFilePath as string, d as Date) as string
    return baseFilePath + ":" + d.SQLDate + "_observation-session-" + _
        Format(d.Hour, "00") + "-" + Format(d.Minute, "00") + "-" + Format(d.Second, "00") + _
        ".html"
end function

function SplitID(o as APObservation) as Pair
    dim prefixIndex as integer = 0
    dim chCode as integer = 0

    do
        prefixIndex = prefixIndex + 1
        chCode = Asc(Mid(o.ID, prefixIndex, prefixIndex))

        if chCode >= 49 and chCode <= 57="" then="" return="" new="" pair(left(o.id,="" prefixindex="" -="" 1),="" val(mid(o.id,="" prefixindex)))="" end="" if="" loop until="" pair(o.type,="" o.id)="" function="" sub="" writeobjectidmarkup(fo="" as="" aptextfile,="" objectid="" string)="" '="" it="" would="" be="" nice="" to="" find="" other="" websites="" link="" for="" various="" catalogs="" such="" ngc.="" left(objectid,="" 1)="M" fo.write("["="" +="" "](http:="" en.wikipedia.org="" wiki="" messier_"="" mid(objectid,="" 2)="" ")")="" else="" fo.write(objectid)="" writeobjectdescriptionmarkup(fo="" obj="" apobservation)="" len(obj.type)=""> 0 then
        fo.Write(" a " + obj.Type)
        if Len(obj.Constellation) > 0 then
            dim constellation as Constellation = Constellation.GetConstellation(obj.Constellation)
            fo.Write(" in the " + constellation.Name + " constellation")
        end if
    end if

    if Len(obj.Name) > 0 then
        fo.Write(" (also named " + obj.Name + ")")
    end if
end sub

sub WriteObserved(fo as APTextFile, key as string, observedObjectSet as Set)
    dim i as integer
    dim observedObjects(-1) as APObservation
    dim observedObjectKeys(-1) as integer
    dim observedObjectKeyStrings(-1) as string

    redim observedObjectKeys(observedObjectSet.Count - 1)
    redim observedObjectKeyStrings(observedObjectSet.Count - 1)
    redim observedObjects(observedObjectSet.Count - 1)

    for i = 0 to observedObjectSet.Count - 1
        dim oo as APObservation = observedObjectSet.Item(i)
        dim op as Pair = SplitID(oo)
        dim ok as integer = op.right

        observedObjects(i) = oo
        observedObjectKeys(i) = ok
        observedObjectKeyStrings(i) = oo.ID
    next

    if key = "Planet" then
        observedObjectKeyStrings.SortWith(observedObjects)
    else
        observedObjectKeys.SortWith(observedObjects)
    end if

    if key = "Planet" then
        key = "Planets"
    elseif key = "M" then
        key = "Messier Catalog"
    elseif key = "NGC" then
        key = "NGC Catalog"
    elseif key = "HR" then
        key = "Bright Star Catalog"
    end if

    fo.Write("### " + key + Chr(10))

    for i = 0 to UBound(observedObjects)
        dim obj as APObservation = observedObjects(i)
        dim when as Date = new Date(obj.LocalDateTime)

        fo.Write(Str(i + 1) + ". **")
        WriteObjectIDMarkup(fo, obj.ID)
        fo.Write("**")
        WriteObjectDescriptionMarkup(fo, obj)
        fo.Write(" last observed at *" + when.ShortDate + "*")
        fo.Write(Chr(10))
    next

    fo.Write(Chr(10))
end sub

sub main()
    '#############################################################################
    '## USER CONFIGURATION
    '#############################################################################
    dim baseFilePath as string = "Macintosh HD:Users:jeremy:Projects:websites:jeremy.cowgar.com:_content"
    dim observedFilename as string = baseFilePath + ":pages:astronomy:observed-sky-objects.html"
    dim postPath as string = baseFilePath + ":posts"
    '#############################################################################
    '## NO MORE USER CONFIGURATION
    '#############################################################################

    dim observed as new Dictionary
    dim observedObjects as Set = new Set
    dim observedPlanets as Set = new Set

    for each session as APSession in APSession.Sessions()
        dim startedAt as Date = new Date(session.Start)
        dim finishedAt as Date = new Date(session.Finish)
        dim title as string = "Astronomy Observations of " + startedAt.ShortDate
        dim filename as string = observationFilename(postPath, startedAt)
        dim fo as APTextFile = APTextFile.WriteFileUsingPath(filename, true)

        fo.Write("---" + Chr(10))
        fo.Write("title: " + title + Chr(10))
        fo.Write("tags:  astronomy, observation session " + Chr(10))
        fo.Write("---" + Chr(10))

        fo.Write("**Began:** " + startedAt.ShortDate + " " + startedAt.ShortTime + Chr(10))
        fo.Write("**Finished:** " + finishedAt.ShortDate + " " + finishedAt.ShortTime + Chr(10))
        fo.Write("**Seeing:** " + session.Seeing + Chr(10))
        fo.Write("**Transparency:** " + session.Transparency + Chr(10))
        fo.Write("**Site:** " + session.Site + Chr(10))

        fo.Write(Chr(10))

        if Len(session.Notes) > 0 then
            fo.Write(session.Notes + Chr(10) + Chr(10))
        end if

        if session.Count > 0 then
            dim i as integer
            for i = 1 to session.nObservations
                dim obj as APObservation = session.Observation(i)
                dim when as Date = new Date(obj.LocalDateTime)

                dim idPair as Pair = SplitID(obj)
                dim s as Set = observed.Value(idPair.left)

                if s = nil then
                    s = new Set
                    observed.Value(idPair.left) = s
                end if

                s.Remove(idPair.right.StringValue)
                s.Add(obj, idPair.right.StringValue)

                fo.Write(Str(i) + ". **")
                WriteObjectIDMarkup(fo, obj.ID)
                fo.Write("**")
                WriteObjectDescriptionMarkup(fo, obj)
                fo.Write(" observed at *" + when.ShortTime + "*")

                if Len(obj.Notes) > 0 then
                    fo.Write(" - " + obj.Notes)
                end if

                if obj.nResources > 0 then
                    fo.Write(" - with my ")

                    dim j as integer
                    for j = 1 to obj.nResources
                        if j > 1 then
                            fo.Write(", ")
                        end if

                        fo.Write("*" + obj.Telescope(j) + "*")

                        if Len(obj.Eyepiece(j)) > 0 then
                            fo.Write(" (*" + obj.Eyepiece(j) + "*")
                            if Len(obj.OpticalAid(j)) > 0 then
                                fo.Write(" and a *" + obj.OpticalAid(j) + "*")
                            end if
                            fo.Write(")")
                        end if
                    next
                end if

                fo.Write(Chr(10))
            next
            fo.Write(Chr(10))
        end if

        fo.Close()
    next

    dim fo as APTextFile = APTextFile.WriteFileUsingPath(observedFilename, true)
    fo.Write("---" + Chr(10))
    fo.Write("title: Observed Objects" + Chr(10))
    fo.Write("tags:  astronomy " + Chr(10))
    fo.Write("---" + Chr(10))

    // Write the planets first, then other catalogs
    call WriteObserved(fo, "Planet", observed.Value("Planet"))

    observed.Remove("Planet")

    dim keys(-1) as string
    for each k as string in observed.Keys()
        keys.Append(k)
    next

    keys.Sort

    for each k as string in keys
        call WriteObserved(fo, k, observed.Value(k))
    next

    fo.Close()
end sub