NetGalley Follies

So I signed up for NetGalley after doing two reviews using L’s account. I didn’t have to much in the way of hope at first since I didn’t really have a record of reviewing but I thought…what the hell.

I got my first acceptance from MacMillan/Tor: The Origin of Storms by Elizabeth Bear— which was unfortunately a book I already had done a review for. Not wanting to shoot myself in the foot by submitting the same review twice I did another one. Read it here.

Then I got another book, and another (look for new reviews soon). Which brings me to this post.

PDF Galleys

One of the books I was given was Guy Gavriel Kay’s upcoming new book All the Seas of the World published by Penguin Random House Canada. Unfortunately it was a drm’ed pdf. “Unfortunately” because not only did I not want to read a pdf, and not only did I not want to authorize my ereader for drm, it turned out it was the pdf of the hardcover pages which meant it was meant to be read at 6 x 9 and the type was super tiny on all of my devices — and I actually couldn’t read it without glasses which was a non-starter for me.

But I didn’t want to fail on one of my first acceptances—I am not sure how harshly the publishers judge these things. I tried a bunch of different things including trying to convert it to an epub but the drm stymied me. For some reason the de-drm scripts I was using just wouldn’t work on this pdf file even though the documentation implied that it would.

Getting creative

I put it aside. Then I came back to it, tried a bunch of different software to try and embiggen the type and again failed miserably. At this point I was starting to feel threatened by the “machine” and my stubborn kicked in.

A google search found reference to Adobe changing their DRM in relation to pdfs between ADE 2 and 3 (Adobe Digital Editions) with no recourse except to downgrade. I was running ADE 4.1 by this time so I decided to install an old version of ADE (care of the handy Internet Archive link) on my old Mac Mini 2011. This along with an old Version of Calibre and older De-drm script resulted in a functioning, albeit slow, install that finally was able to strip the drm from the pdf.

A bad, bad epub

Next step: Calibre’s handy convert to epub feature gave me a functioning, yet butt-ugly epub.

So I used eCanCrusher to unpack the epub and started to make a new one. Using Standard ebooks tool suite I made a new container and started to copy the text into the new publication, cleaning it up as I went.

The text was pretty messy since the epub convertor can’t differentiate styles, chapter breaks etc. But I’ve been doing this sort of clean up a lot so it took less than an hour to go from pdf to 90% clean ebook. The last 10% will take a close proofread which is what I wanted it for in the first place. Ta-da…take that technology!

Who owns what?

Now I had been making the assumption that as Galleys these books were essentially electronic ARCs (Advanced Reader Copies) which are what publisher’s produce in advance of the publication date to give out to reviewers. It is understood that you aren’t to sell or give away these copies but they make a neat addition to you library…I have a bunch of paper ones from past projects.

But I noticed in ADE that, like a traditional library loan, these books had status dates on them. Does that mean my review copy expires? Boo…Hiss!

I guess I will have to wait the 53 days in order to find out, but if so this is just another way that I think the whole ebook publishing market is one big scam. What’s even more ironic is that the Gladstone book (up next after Kay) is published by Tor who eschews DRM altogether. So if I buy a book from them it won’t have drm—but seemingly these galleys do and it will expire like any other library book. I am not sure the value exchange is fair here…I get to read a book a month or two earlier in exchange for my review and personal promotion, but I don’t actually get to reread the book in the future unless I buy it (or take it out from a library). Sheesh…talk about chintzy…

I mean I get that digital materials are way too easy to pass around but how about a little faith? Of course I guess after all that work I can hang on to my newly converted epub, but that just seems like cheating.

Addendum

I checked the NetGalley site and apparently the books do indeed expire after 55 days with the option for another 55 day renewal, up until the archive date—which is when the publishers pull them from the site. Except for Kindles:

*If you have used the Kindle option to send a copy of the file to your Kindle, that file will not expire, and will continue to be available to you.

Which is a total crock given how proprietary Amazon is. Maybe I will trying the Kindle app instead so I get to keep ’em. Of course that is like jumping from the frying pan to the fire…

Addendum Part 2

A bit more investigating yielded this:

How It Works

To put a book on NetGalley, authors will first need to complete a contract and submit a payment form. Most authors will likely select from one of the following pricing options: the basic six-month listing option, which is priced at $399, and the Marketing-Plus-Title listing, priced at $599, which includes placement in the NetGalley Newsletter. Indie authors who are members of the Independent Book Publishers Association can take advantage of the organization’s relationship with NetGalley. Through the IBPA partnership, indie authors can list their books at discounted prices ($349 for a standard six-month listing; $499 for a package enhanced by marketing features). In addition, IBPA will do most of the work involved in adding books to NetGalley and processing requests.
publishersweekly.com/pw/by-topic/authors/pw-select/article/68517-the-savvy-self-publisher-s-guide-to-netgalley.html

Ahh, the world we live in, where everything is for sale. Another “review” site apparently charges $2/review but that’s ok because the money doesn’t go to the reader…it goes to the company. Right. That makes it ok. Not. So the self-publisher is getting screwed, the reviewer is getting screwed, and the big 5 (or is it 4 now?) reap the benefits of increased sales and exposure at a pretty minimal per/unit cost.

TANSTAAFL.

Sunday Poem Day

Sea Life
What will he see?

Seven seagulls sit on shore
Sixteen seagulls prefer to soar.

Several seals swim at sea
Sinking slowly ‘neath the shimmery.

Sardines swim from snapping seals
Sensing safety in swift shiny snarls.

Snuggled scallops sift through the sand
Seriously satisfied to stay suntanned.

And the whale watches wonderingly…

“Spicy”

spiceitupp.com/curry-powder-vs-garam-masala-powder/

Blends vs Spices

Who knew? Well I did, but I will admit I really didn’t understand. Although “curry” and “Garam Masala” are sold as spices they are, in fact, spice blends. What I didn’t know is that they are pretty similar in constituent parts (turmeric seems to be the big difference along with chilli powder).

According to the article and chart Garam Masala focusses on the “stronger pungent spices” like cloves, cinnamon, cardamom as opposed to curry powder, which uses more “mild spices like turmeric, cumin, coriander and fenugreek” which tend to be “sweet mild spices.” Being someone who thinks “mild” is usually way too hot this is a bit of a revelation.

Recipe confusion

What is got me thinking about all this is that recipes often call for one or the other and occasionally even add in even more spices. I am not sure if there is an international recognized “curry” standard but my guess is not — so that means you are rolling the dice a bit every time you try a new recipe. It’s a coincidence, but my randomly chosen “go to” curry recipe doesn’t call for either blend. Instead it asks for:

Spice blend
– 1 1/2 tsp ground coriander
– 1 tsp ground cumin
– 1/2 tsp turmeric
– 1/2 tsp ground cinnamon
– 1/2 tsp ground black pepper
– 1/4 tsp ground mustard
– 1/4 tsp ground cloves
– 1/4 tsp cayenne

Which I now discover (according to the chart) is mostly a curry powder. I don’t own any cardamom or fennel seed but I guess I should get some to be more authentic. 😉 Still, I guess I am bit proud of the fact my subconscious decided to go for a custom blend rather than a prepackaged blend. Maybe next I will try grinding my own spices from whole…lol.

Aftertaste

Ironically I didn’t have any mustard or coriander last time I made it so I added in a bit of Garam Masala… I guess that really crossed a line in terms of authenticity… but we ate it anyway—and it didn’t kill anyone. Which is pretty much all I ask of my cooking.

Books and Reviews

For a lark I have decided to move/copy my book reviews to their own sub-site: https://macblaze.ca/books/

Hopefully I will start to do more reviews regularly and see if I can build up a solid block of reviews (maybe even enough to call myself a book reviewer 🙂 ). I might consider posting my book-related stuff like my book counts there as well.

Saturday Review Two. On Monday…

Where to start? This is the second of my reviews for NetGalley. Unfortunately it’s book three of a series that is a continuation of another three-book series. Quite the place to start…talk about in media res. Still we soldier on, noblesse oblige and all that…or is it just contractual obligation? Whatever…

The Origin of Storms

Elizabeth Bear
Book 3 of The Lotus Kingdoms

Elizabeth Bear is probably one of the most versatile authors I know. I first met her way back in 2005 with her Jenny Casey books and have been following along ever since. Sometimes she thrills me and sometimes I find her prose/subject mater just a tad intimidating, but I have never failed to finish a book of hers other than satisfied. Which is quite the accomplishment given the massively disparate subject matter (from Norse mythology to AI-driven space opera and pretty much working away on everything between) she tackles.

The Origin of Storms is book 3 of The Lotus Kingdoms series, which itself is the second trilogy that takes place in the worlds of the Eternal Sky. As in a lot of the fantasy of this genre, Bear uses the first two books to set up the final conflict between “good” and “evil” (although it’s, thank goodness, much much more nuanced than that), and starts this third and final volume with the minor villains disposed of, the armies arrayed, heroes/heroines girded and final conflict looming. And then off the story goes, upsetting the form, exploring motherhood, “stewardship” and the real meanings of power and responsibility. At least that’s what I took from it. The great thing about Bear is when she’s in top form, the story’s pretty darn dense and there’s always lots and lots you can take away. I think The Origin of Storms is pretty high up in the Bear canon.

While the first series had an Asian steppes flavour, this one moves the action to a south-Asian milieu with more rajahs and fewer horses. The conflicts are rooted in a fallen empire and the struggles of the multiple heirs to secure their own borders and destinies. As we start The Origin of Storms we realize perhaps the conflict is bigger than simple, mortal jealousies and ambitions — that perhaps these children of empire have inherited something much larger and more dangerous than they expected.

One think I liked, and this is a tad provocative, is Bear’s handling of oft-touchy issues like race, gender, sexuality and equality, etc. that are slowly (or quickly, depending on your viewpoint) coming to the forefront in SciFi/Fantasy publishing. To me, Bear delivers a smooth story chock full of diversity without really making a big deal of it—it just is, as it should be. Integral to the story, unremarkable except when it’s not and delivered with a smooth touch that leaves very little for anyone to get their shorts in a knot about.

Anyway, it’s a great book, a great conclusion to a great series and leaves me both wondering and keen to find out where Bear will take us next.

Poem Day: Her Day

Animal Friends on a Hop-Happy Day

Tim is a scruffy rabbit
who nibbles on the ratty lawn.
And he’s got special, special friend
by the sunny name of Dawn.

And Dawn’s got another friend,
a clever grey squirrel named Anne.
From high atop the biggest tree,
she’s Dawn’s second biggest fan.

And far, far, far overhead,
flies a daffy mallard named Alexander.
He’ll often say nice things about Dawn
but it’s usually a back-hander.

And as she’s just a tiny fawn,
Dawn is generally quite shy.
Sooo quiet, and timid, and wary,
that brash Tim will often sigh:

Come out, come out from that shrub!
It’s time for us to play!
Let’s romp though the grassy fields
because it’s your special, special day.

And sometimes on those special days,
shyly, slyly smiling, out she’ll come.
And Anne and Tim and Alex and Dawn,
through the world they’ll run.

But sometime she won’t,
and that’s also okay,
because they all know
there’ll always be another day.

And that day,
will be
Dawn’s
special, special day.

Saturday’s Python Lesson

I have been dabbling more and more with Python. Python is a programming language (that, FWIW, comes pre-installed on a Mac) that is used by a lot of data scientists. As programming languages go it isn’t too hard to learn and is really versatile. One of the things that makes it so versatile is that it can use outside modules and libraries easily and there seems to be a module that will do just about anything you can want.

Why

A few years back I tried to convince L to use the import function built into Blackboard (MacEwan’s LMS [Learning Management System]) to import quiz questions and move from paper-based marking to a more automated workflow. It didn’t work, but in the process I did build a php module to build quizzes.

Then COVID happened.

But, no, before you jump to conclusions, I didn’t manage to convince her to use the bulk import even though she started to use the quiz modules to deliver and mark the quiz. Baby steps.

Then Moodle happened.

MacEwan is in the process of giving up on Blackboard and transitioning to Moodle — which is an open-source LMS. As it happens L has another, temporary, teaching gig at a different institution that also uses Moodle — this was a lot of additional work and learning, so she was starting to come around to the idea I might be able to help.

As a result, eventually, with great sighs and heaving shoulders, she gave in to my pestering and allowed me to upload one of her quizzes… and lo and behold she was impressed at the ease! Minus a few technical glitches.

My End

What I had done was use the format info from my previous php project. Then I used her docx file and by saving it as a text file I was able to do a few search and replaces via regex to create an upload compatible file. Blackboard wants files to look like:

TF  True or false? For Niklas Luhmann, the individual agent is not integral to society.   TRUE
MC  In the sentence "Maybe I got mine, but you'll all get yours.", what part of speech is "yours"?  pronoun CORRECT adjective   INCORRECT   preposition INCORRECT   noun    INCORRECT

Version One

…of my process was simply to build the regex. Luckily she used a pretty standard format to write the questions so I just had to find the pattern and use it to change it to the proper format.

TRUE/FALSE

True or false? For Niklas Luhmann, the individual agent is not integral to society.

True
False

PRONOUNS

In the sentence “Maybe I got mine, but you’ll all get yours.”, what part of speech is “yours”?

pronoun
preposition
noun
adjective

Find:
(.*?)\n\n(.*?)\n(.*?)\n(.*?)\n(.*?)\n\n

Replace with:
MC\t\1\t\2\tCORRECT\t\3\tINCORRECT\t\4\tINCORRECT\t\5\tINCORRECT\n

In English this says find: anything (group1) followed by 2 line breaks followed by anything (group2) followed by 1 line break followed by anything (group3) followed by 1 line break followed by anything (group4) followed by 1 line break followed by anything (group5) followed by 2 line breaks

Replace it with: MC tab Group1 tab Group2 tab CORRECT tab Group3 tab INCORRECT tab Group4 tab INCORRECT tab Group5 tab INCORRECT line break

Easy, right? It was slightly different for the True/False questions as there was only two answers but followed the same principles.

Version Two

…added a python script that looked for the ALL CAPS and split the file into two separate files. At which point I also wrote in a search and replace of ‘’ and “” into ' and " since Blackboard didn’t like the special characters.

Version Three

…combined the original regexes with the python script and did it all in one pass. Success! I also added a randomization bit so she could leave the first Multiple Choice answer as the Correct one and the script would randomize them before upload.

Of course when I went to demo the speed and efficiency of my “wondrous creation” to L I forgot to convert the docx to a txt file and it failed. But I soldiered on, did the necessary step and then proceeded — but the “burning shame” of failure remained and so…

Version Four

…added a docx import module and that’s where I am now.

Given an Word docx file with sections delineated by titles in ALL CAPS, this script will divided it into several text files named after the sections, convert curly quotes , format the questions in Multiple Choice or True/False format, and randomize the MC answers.

The resulting files can be uploaded to Blackboard’s question pool for use in multiple quizzes. Of course now I have to do it all over agin for Moodle as it uses a completely different import format 🙂

# import necessary modules
import os
import random
import re

import pypandoc

# NOTE Sections must be in ALL CAPS. They must be named TRUE FALSE (or TRUE / FALSE)
# or else be in the Multiple Choice format.

# set directory to current path of python file
directory_path = os.path.dirname(__file__)

# get file name
print('Enter the filename (without.docx):')
filename = input()

# set docx file and output file
docxFilename = directory_path + "/" + filename + ".docx"
outputfilename = directory_path + "/" + filename + ".txt"

# use pandoc to convert docx to txt
output = pypandoc.convert_file(
    docxFilename, 'plain', outputfile=outputfilename,
    extra_args=['--wrap=preserve'])
assert output == ""

# Open the converted file
filecontents = open(
    directory_path + "/" + filename + ".txt", "r")

# Assigns the variable filecontents the contents of filename.txt, not just the location of the file
filecontents = str(filecontents.read())

# Finds all the ALL CAPS in the file and makes a list (section) of all the sections
sectionname = re.compile(
    r'\n(?=[A-Z])([/A-Z\s]+)\n')
section = re.split(sectionname, filecontents)

# Removes the preamble in list and starts with first ALL CAPS section
section.pop(0)

# Loops for the number of sections in the file, starting at the first split 
# looking for every 2nd section (the contents rather than the title)
for i in range(0, len(section)+1, 2):

    # Set section name and strip out extra characters
    sectionname = section[i-2][:-1]
    sectionname = re.sub("[/|\s]", "", sectionname)

    # Opens a file with the name of ALL CAPS sections; if it does not exist, it creates one
    writeFile = open(
        directory_path + "/" + "split-files/"+sectionname+".txt", "w+")

    # sets text to item (contents) in the list after ALL CAPS delimiter
    text = section[i-1]

    # strips out curly quotes
    text = text.replace('“', '"').replace(
        '‘', "'").replace('”', '"').replace('’', "'")

    # if the sectionname is TRUEFALSE then...
    # then use regex to  format questions as TF otherwise format as MC
    if sectionname == "TRUEFALSE":
        # Substitute all patterns in one go
        text = re.sub(r'(.*?)\n\n(.*?)\n\n(.*?)(\n\n|\n\Z|\Z)',
                      lambda x: 'TF \t' + x.group(1) + '\t' + x.group(2).upper() + '\n', text)
        writeFile.write(text)
    else:
        # else loop though text, match pattern and name capture groups. Uses ?P<name> to name groups
        for m in re.finditer(r'(?P<qq>.*?)\n\n(?P<one>.*?)\n\n(?P<two>.*?)\n\n(?P<three>.*?)\n\n(?P<four>.*?)(\n\n|\n\Z|\Z)', text):

            question = m.group('qq')
            # write capture groups of answer into a list so we can randomize it
            qlist = [m.group('one') + "\tCORRECT", m.group(
                'two') + "\tINCORRECT", m.group('three') + "\tINCORRECT", m.group('four') + "\tINCORRECT"]
            # randomize list
            random.shuffle(qlist)

            # construct question and answers
            text = "MC\t" + question + "\t" + qlist[0] + "\t" + qlist[1] + "\t" + \
                qlist[2] + "\t" + qlist[3] + "\t\n"

            # Write to file
            writeFile.write(text)

    writeFile.close()  # Finally, it closes the text file