20180618

Post Scriptum Mortar Calculator


If you find the app helpful, I and my cat would appreciate any support you could send our way.


App is released for free, with no annoying ads and will ask for no permissions. I hope you will all appreciate this. Any gifts will keep a thirsty developer in some beer - and recoup the 25USD for the Android Developer Account. Also it will go to keeping the cat distracted by Tuna bribes in order to stay off my keyboard...

(The surrender tuna or keyboard look...)

VERSIONS:

Version format: [major release].[new feature(s)].[bugfix patch-version] 
0.0.9: Public beta test version
1.0.0: First Release
- Fixed divide by zero bug crashing the app 
- Added Mils calculation 
- Added current mortar models and selection between them 
- Added About button linking to blog with instructions 
1.1.0: Second Release
- Added minimum range for the various mortars 
1.2.0: The Yanks are coming!
- Added US 4.2" Mortar 
1.2.1: Simplifying it
- Ripped out the 4th coordinate as it confused quite a few people 
- Changed Android API version to comply with latest requirements from Google Play
1.3.0: Le Baguette
- Added French mortars
- Fixed a slight issue where on some aspect-ratios, button-text could go outside the button boundary

USAGE:

Enter in coordinates for Mortar and Target position using the keypad. For the first coordinate, hitting the key once, twice or thrice will change between the letters printed on the key. You know, like the good old times writing SMS messages on our phones. When done, hit the '>>' key on the keypad.

The second coordinate can be either a single or double digit number. For a single digit number, hit the selected number you want, and then hit the '>>' key. For double digit, first enter in one number and then the other before hitting the '>>' key. Couldn't be simpler.

The next two coordinates are single digit only. Change between them using the '>>' (next) or '<<' (previous) keys. You get these from the in-game map.

To change between entering mortar coordinates and target coordinates, hit either the 'MRT' or 'TGT' button.

When satisfied, hit the 'Calc' button. To change between coordinates, use '<<' and '>>' on the keypad. To change Mortar model (important for correct mils calculation), hit the '<<' and '>>' buttons on the upper row above the display. Changing mortar will automatically recalculate the mils value.

The 'About' button will take you to this screen.

FUTURE:

Next version will be released to coincide with the 'Post Scriptum Big Update!' that should feature a new faction - and thus at least one new mortar.

FAQ:

Q: Why not an iOS version?
A: Hey, buy me a Mac, an iOS device and 100USD to cover the (yearly) Apple Developer subscription, and I can push out a version for iOS in less than a day!

Q: What was used to develop this App?
A: App Game Kit 2 by The Game Developers. It's basically a language and C++ library to facilitate more or less pain-free cross-platform 2D and 3D app development. No 'code-by-menu-hunting' approach as in Unity, but good old writing code into an IDE and compile/export.

Also GIMP for creating the graphical assets, and Audacity to edit the little clicky sound.

Q: Is it Open Source?
A: Yes - and no. The code I've written for this app is under MIT License. However the underlying App Game Kit framework and runtime is proprietary and owned by The Game Creators Ltd.

My code for this app is available at https://github.com/rDybing/PS_RangeBearing

Do note that any graphical assets are not included in that repo.

20180525

Changing values in a slice in a struct in a map...

Maps in Go are great as a out of the box simple key-value datastructure. However, maps can be a bit rigid from time to time. For instance, adding new instances into a slice in a struct in a map reference had me scratching my head quite severly.

So I made a little demo-project to work out the procedure. This is a bit clunky I must admit, but it do work.

---
package main

import (
    "crypto/sha1"
    "fmt"
    "hash"
    "io"
    "math/rand"
    "time"
)

type myStructT struct {
    name string
    pets []string
}

func main() {
    var myMap map[string]myStructT
    myMap = make(map[string]myStructT)

    rand.Seed(time.Now().UTC().UnixNano())
    mySlice := initSlice()
    myMap = initMap(mySlice)
    printMap(myMap)
    myMap = editMap(myMap, "Dewey")
    fmt.Println("----- After edit -----")
    printMap(myMap)
}

func editMap(in map[string]myStructT, index string) map[string]myStructT {
    var h hash.Hash
    var hash string
    var old myStructT

    h = sha1.New()
    io.WriteString(h, index)
    hash = fmt.Sprintf("%x", h.Sum(nil))

    old = in[hash]
    delete(in, hash)
    old.pets = append(old.pets, "Alligator")
    in[hash] = old
    return in
}

func printMap(in map[string]myStructT) {
    for i := range in {
        fmt.Printf("Name: %s\n", in[i].name)
        if len(in[i].pets) > 0 {
            fmt.Printf("Pets: %d\n", len(in[i].pets))
            for j := range in[i].pets {
                fmt.Printf("- %s\n", in[i].pets[j])
            }
        } else {
            fmt.Println("No Pets :(")
        }
        fmt.Println("----------")
    }
}

func initSlice() []myStructT {
    var s myStructT
    var out []myStructT

    name := [3]string{"Huey", "Luie", "Dewey"}
    pets := [6]string{"Cat", "Dog", "Ferret", "Bunny", "Hamster", "Parrot"}

    for i := range name {
        s.name = name[i]
        s.pets = nil
        x := randInt(0, 3)
        for j := 0; j < x; j++ {
            y := randInt(0, 6)
            s.pets = append(s.pets, pets[y])
        }
        out = append(out, s)
    }
    return out
}

func initMap(in []myStructT) map[string]myStructT {
    var h hash.Hash
    var hash string
    var s myStructT

    out := make(map[string]myStructT)

    for i := range in {
        h = sha1.New()
        io.WriteString(h, in[i].name)
        hash = fmt.Sprintf("%x", h.Sum(nil))
        s = in[i]
        out[hash] = s
    }
    return out
}

func randInt(min int, max int) int {
    return min + rand.Intn(max-min)
}

---

Essentially what happens is that I import the map, copy the given index I want to modify into a temp struct. Modify the temp struct as per usual procedure. Then kill the map instance of the given index, add a new map instance using the same index, and fill it with the modified content of the temp struct.

Finally, return to sender.

Hopefully I can find a better solution, I think I've read something about using pointers to operate directly on the map struct.

If I got it right, the map will then only contain a pointer to a given struct and it's instance. I'll have to read some more, ask around and lubricate my brain with beer to get there though...