Day 2 of Hanukkah at Anvil

Build a web app for each night of Hanukkah, with nothing but Python!

A cornucopia of options

It’s the second night of Chanukah: time for an argument. How do you spell Hanukka?

https://but-how-do-i-spell-it.anvil.app

In today’s app, we provide you with a bounty of transliterations of חֲנוּכָּה‎, for both your enjoyment and fury.

How is the front end made?

We get started by choosing the ‘Hello San Francisco’ style when creating a new app, and choosing the ‘Standard’ theme for our app page. We replace the header.jpg asset with a suitably wintery image so that our header shows something a little more seasonal than the sweeping skyline of San Fran, and then we’re ready to start building the UI!

We add the title, the button (called spelling_button) and a label (called spelling_label) below that which will eventually display the spelling. However, we don’t want that spelling label - and its default text - to be visible before the user hits the button, so in the Form’s startup code, we make sure to hide that label.

    class Form1(Form1Template):
    def __init__(self, **properties):
        self.init_components(**properties)
        self.spelling_label.visible = False # hide the label

Now, we want to make something happen when the button is clicked, so we set its event handler for the click event.

  def spelling_button_click(self, **event_args):
    """This method is called when the button is clicked"""
    self.spelling_label.visible = True # show the label
    self.spelling_label.text = anvil.server.call('get_random_spelling')

This code means that when the button is clicked, a server function called get_random_spelling will be called, and its return value will be shown in the spelling_label. Great! Now we need to actually write that server function.

How is the back end made?

We make a new Server Module to house our get_random_spelling function, and decorate our function with the @anvil.server.callable decorator so that we can call it from the client.

@anvil.server.callable
def get_random_spelling():
  spelling = "{chet}a{nun}u{kaf}a{he}".format(
    chet=get_letter_spelling('chet'),
    nun=get_letter_spelling('nun'),
    kaf=get_letter_spelling('kaf'),
    he=get_letter_spelling('he')
  )
  special_spellings = random.random_sample()
  if special_spellings < 0.02:
    if random.random_sample() < 0.01:
      spelling = "Just use the Hebrew."
    else:
      spelling = "Janice"
  return spelling

def get_letter_spelling(letter):
  spellings_dict = {
    'chet': {'spellings': ['H', 'Ch','Ḥ', 'X', 'Kh'], 'chances': [0.45, 0.35, 0.15, 0.04, 0.01]},
    'nun': {'spellings': ['n', 'nn', 'nnnnn'], 'chances': [0.5, 0.45, 0.05]},
    'kaf': {'spellings': ['k', 'kk', 'ck'], 'chances': [0.5, 0.45, 0.05]},
    'he': {'spellings': ['h', '', 'hhhhhhh'], 'chances': [0.7, 0.27, 0.03]}
  }
  table = spellings_dict[letter]
  spelling = random.choice(table['spellings'], p=list(table['chances']))
  return spelling

The get_letter_spelling function define a table of probabilities for each letter’s transliterations, using the numpy.random.choice function. The choice function creates a discrete random variable with the given probabilities. So, for chet, we’ve defined the following:

  • 45% chance it’ll come out as H
  • 35% chance it’ll come out as Ch
  • 15% chance it’ll come out as
  • 4% chance it’ll come out as X
  • 1% chance it’ll come out as Kh

Then, for each letter, it returns a spelling choice and we substitute that back into the base string "{chet}a{nun}u{kaf}a{he}".

The following snippet adds a couple of extra, special options:

  special_spellings = random.random_sample()
  if special_spellings < 0.02:
    if special_spellings < 0.01:
      spelling = "Just use the Hebrew."
    else:
      spelling = "Janice"

random.random_sample() generates a random float in the interval [0, 1). If it’s less than 0.02, a 2% chance, then we get a ‘special spelling’ - one that didn’t quite fit into the schema we defined above. There’s a 1% chance each of getting Janice or Just use the Hebrew. as your ‘spelling’ - see how many times it takes for you to get them to pop up on the app!

Once we’re done generating a spelling, it gets passed back to the client code and displayed there: the spelling_button_click function sets the spelling_label’s visibility to True, and sets the text to be the spelling we just got from the server.

That’s it!

And that’s it! Go forth and generate some spellings!




Give the Gift of Python

Share this post:


Get tomorrow's app in your inbox

Don't miss a day! We'll mail you a new web app every night of Hanukkah: