diff --git a/README.org b/README.org index c1f6921..0f0fffa 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,6 @@ # -*- mode: org; coding: utf-8; -*- -* S.P.A.C.E (working title) +* Superject (working title) #+BEGIN_QUOTE A proposition, for Whitehead, is neither true nor false in itself. It is a lure for feeling the world that “might be.” A proposition is what places a concrescing subject (an occasion of experience) in relation to a potential predicative pattern. It is the potential togetherness of subject and predicate that characterizes a proposition and not its actual exemplification. But propositions do not hang in the thin air of abstraction; they always emerge from somewhere and are entertained by an actual subject within a particular milieu. The proposition’s relevance and importance (or its “truth”—in William James’ sense) is contingent upon the world that it finds itself within. @@ -12,13 +12,14 @@ Various notes can be found in the ~notes/~ folder * propositions (cards) -Card design can be found in the ~cards/~ folder and rendered cards can be found in the ~cards/_ouput~ folder. Ways of using the cards can be found in file:Process&Reality.org +Card design can be found in the ~cards/~ folder and rendered cards can be found in the ~cards/_ouput~ folder. Ways of using the cards can be found in [[file:Process and Reality.org]] - testing deck creating using [[https://github.com/andymeneely/squib][squib]] - edit card descriptions in the ~cards.txt~ files - change layout in the ~layout.yml~ file(s) - change design logic in the ~deck.rb~ file +#+ATTR_org: :width 600px #+CAPTION: cards (example) [[file:cards/img/_example.png]] diff --git a/cards/deck-neural.rb b/cards/deck-neural.rb new file mode 100755 index 0000000..42a9ce3 --- /dev/null +++ b/cards/deck-neural.rb @@ -0,0 +1,200 @@ +#!/usr/bin/env ruby -W0 + +# aprox. running time +# ./deck-neural.rb 144.08s user 10.49s system 28% cpu 8:55.15 total +# ./deck-neural.rb 155.95s user 10.38s system 30% cpu 9:00.29 total +# cards-36.csv +# ./deck-neural.rb 30.74s user 2.63s system 105% cpu 31.507 total +# 50 cards +# ./deck-neural.rb 76.23s user 6.31s system 132% cpu 1:02.50 total + +require 'squib' +require 'rest-client' +require 'open-uri' +require 'json' +require 'digest' +require 'mini_magick' +require 'unsplash' +require 'pexels' + +# cards from local csv and images vis text2image GAN +# https://deepai.org/machine-learning-model/text2img +$deepai_api_key = "59b70a3d-d42a-42be-979d-d09ec08ec7e0" + +$pexels_api_key = "563492ad6f917000010000016e741b30a565426c90e5b65b6b34063b" + +# prod the GAN in a potentially relevant direction with a keyword or phrase prefix +$keyword = "" + +# where to get images? try "t2i" or "unsplash" or "pexels" +$img_source = "unsplash" + +# cards descriptions +#$cards_csv = 'cards-p50-1.csv' # 23:02 +#$cards_csv = 'cards-p50-2.csv' # 21:24 +#$cards_csv = 'cards-p50-3.csv' # 22:52 + +# unsplash config +Unsplash.configure do |config| + config.application_access_key = "FWIsA-zAhsj3biPbVH3-H6qoeB30EVazjQpIjlrnaoE" + config.application_secret = "Qcr0ETekpsPVMsGBRSmHSsF7NvAnqWkiZmKw9KP9Ros" + config.application_redirect_uri = "urn:ietf:wg:oauth:2.0:oob" + config.utm_source = "pandemic" +end + +# cards descriptions input from csv +data = Squib.csv file: $cards_csv + +# text2image slurp + +def get_img_t2i (phrase) + puts "test2img> #{$keyword} #{phrase}" + d0 = Digest::RMD160.hexdigest phrase + r0 = RestClient::Request.execute(method: :post, url: 'https://api.deepai.org/api/text2img', timeout: 600, + headers: {'api-key' => $deepai_api_key }, + payload: { 'text' => "#{$keyword} #{$phrase}" } ) + f0 = "img/#{d0}.png" + t0 = MiniMagick::Image.open(JSON.parse(r0)['output_url']) + t0.format('png').write(f0) + puts "wrote: " + f0 + return f0 +end + +# unsplash +# - https://github.com/unsplash/unsplash_rb +# - https://www.rubydoc.info/github/unsplash/unsplash_rb/ + +def get_img_unsplash (phrase) + puts "unsplash> #{$keyword} #{phrase}" + d0 = Digest::RMD160.hexdigest phrase + r0 = Unsplash::Photo.random(query: "#{$keyword} #{phrase}", orientation: "squarish") + + if true + f0 = "img/#{d0}.png" + t0 = MiniMagick::Image.open(r0.urls.regular) + t0.format('png').write(f0) + puts "wrote: " + f0 + return f0 + else + p "couldn't find an image for #{$keyword} #{phrase}..." + return "img/blank.png" + end + rescue + p "wonk? err..." + return "img/blank.png" +end + +# pexels +$pxl = Pexels::Client.new($pexels_api_key) + +def get_img_pexels (phrase) + puts "pexels> #{$keyword} #{phrase}" + d0 = Digest::RMD160.hexdigest phrase + r0 = $pxl.photos.search("#{$keyword} #{phrase}", per_page: 1) + f0 = "img/#{d0}.png" + if !r0.photos.empty? + r1 = r0.photos[0].src["portrait"] + t0 = MiniMagick::Image.open(r1) + t0.format('png').write(f0) + p "wrote: " + f0 + return f0 + else + p "couldn't find an image for #{$keyword} #{phrase}..." + return "img/blank.png" + end +end + +# other options for automated image collation +# - https://pixabay.com/api/docs/#api_search_images +# - https://github.com/public-apis/public-apis#photography +# - https://en.wikipedia.org/wiki/Wikipedia:Public_domain_image_resources +# - https://commons.wikimedia.org/wiki/Category:Images +# - https://rapidapi.com/collection/image-apis + +#layouts = ['economy.yml', 'space-layout-1.yml'] +layouts = ['space-layout-3.yml'] + +c1 = '#9f68ed' +c2 = '#ed9f68' +c3 = '#b5ed68' +c4 = '#eeeeee' + +# conditional coloring +# https://squib.readthedocs.io/en/v0.15.0/colors.html?highlight=color#samples + +color = c1 + +Squib::Deck.new cards: data['name'].size, width: '38mm', height: '60mm', layout: layouts do + + # set background colour per card type + bg = data['type'].map do |t| + if (t.eql? 'O') + c1 + elsif (t.eql? 'Q') + c2 + elsif (t.eql? 'Q') + c3 + else + c4 + end + end + + # set fill colour per card type + fg = data['type'].map do |t| + if (t.eql? 'O') + c2 + elsif (t.eql? 'Q') + c1 + elsif (t.eql? 'Q') + c4 + else + c4 + end + end + + # associative image search and/or generation + # https://experiments.runwayml.com/generative_engine/ + # https://deepai.org/machine-learning-model/text2img + + # generate & collect images + case $img_source + when "t2i" + dlimages = data['name'].map { |i| get_img_t2i i} + when "unsplash" + dlimages = data['name'].map { |i| get_img_unsplash i} + when "pexels" + dlimages = data['name'].map { |i| get_img_pexels i} + else + puts "unknown image source " + $img_source + end + + # sharing & colours + background color: bg + rect fill_color: fg , x: '3mm', y: '3mm', width: '32mm', height: '54mm', radius: 32 + + #rect layout: 'cut' # cut line as defined by TheGameCrafter in economy.yml + #rect layout: 'safe' # safe zone as defined by TheGameCrafter in economy.yml + + # in z-order low->high + text str: data['text'], layout: 'description' + png file: dlimages, layout: 'illustration' + png file: dlimages, layout: 'overlay' + text str: data['type'], layout: 'type' + text str: data['name'], layout: 'title' + + # output a png of each card + tag = Time.now.strftime('%Y%m%d_%H%M') + + save format: :png, prefix: "cards_#{$keyword}_#{tag}_#{$img_source}_", count_format: '%d' + + #.. and pdf of the deck on A4 + # see also https://squib.readthedocs.io/en/v0.15.0/sprues.html#list-of-sprues + save format: :pdf, file: "deck_#{$keyword}_#{tag}_#{$img_source}.pdf", + width: '297mm', height: '210mm', margin: '20mm', + crop_marks: true, + crop_stroke_width: 0.5 + + #save_png + #save_pdf + +end diff --git a/cards/img/blank.png b/cards/img/blank.png new file mode 100644 index 0000000..c530caf Binary files /dev/null and b/cards/img/blank.png differ