Pierre Morsa

ce bon vieux blog

Réflexions de comptoir

Comment ajouter de la magie dans votre pitch

Un des points que nous expliquons souvent aux Startups est qu’elles doivent expliquer la « Magie » de leur solution.

La magie, c’est l’ingrédient secret qui fait qu’une solution est meilleure que les solutions concurrentes ; c’est la raison pour laquelle les utilisateurs voudront acheter un produit plutôt que celui d’une autre société.

Cependant la magie est intangible, et parfois les Startups restent bloquées sur des idées de « magie » bien trop techniques ou alambiquées. Aussi je vais donner ici quelques exemples pour bien montrer les différentes façons de mettre de la magie dans votre produit.

La magie de la simplicité

Prenez Capitaine Train, aujourd’hui nommé Trainline. Cette startup est née d’un constat : le service de réservation en ligne de la SNCF était incroyablement mal fichu, lent et compliqué. Leur magie ? La simplicité et la rapidité de réservation. La SNCF a mis des années avant de réagir et proposer une App et un site convenables.

La magie du marketing

Prenez une bouteille de Coca, prenez une bouteille de Pepsi. La plupart des personnes préféreront l’eau sucrée marron de la bouteille de Coca à la bouteille d’eau sucrée marron de Pepsi. Pourquoi ? Un ingrédient secret dans la formule ? Non. L’ingrédient secret qui a fait la force de Coca-Cola, c’est le marketing.

La magie de l’égocentrisme

« Parce que je le vaux bien » dit la pub de l’Oréal. Mais au fond je vaux bien quoi ? Le droit d’acheter une bouteille de shampooing ? Euh… ben… en fait au moment où j’entends le slogan je vaux bien ce que mon Ego me dit que je vaux, et piqué à vif mon Ego me dit que je vaux beaucoup. C’est également pour ça que des gens achètent des marques de luxe.

La magie de la performance

Tous les produits ne se basent pas uniquement sur du marketing ou sur la flatterie de l’Ego. Certains produits gagnent car leur magie repose sur leurs performances objectivement meilleures. Par exemple, on peut penser ce que l’on veut de Google, mais la réalité est que les résultats de leur moteur de recherche sont bien meilleurs que ceux des concurrents.

La magie de la commodité

C’est assez proche de la simplicité, mais la commodité (d’emploi) repose surtout sur la facilité à utiliser un produit. Les soupes en boîte, les plats surgelés, les capsules de café, tous ces produits reposent sur la commodité d’emploi. Par exemple le café en grains a été supplanté par le café moulu, qui est lui-même aujourd’hui bien souvent remplacé par le café en capsules. La salade fraîche entière non lavée a été remplacée par la salade en sachet.

La magie de la magie

Parfois, un produit est magique parce que ce qu’il est capable de faire défie tout ce qui existe. Quelques exemples évidents : la voiture, l’ordinateur personnel, l’iPhone, les vaccins.

En conclusion

Vous pouvez rendre votre produit magique de bien des façons, et je n’en ai listé ici qu’une partie ; l’idéal est de le rendre magique de plusieurs manières. N’oubliez pas non plus de faire attention à la valeur sociale de votre produit, pour ne pas qu’il soit tué dans l’œuf par le « ridicule factor ».

Articles liés

Ne modifiez pas une présentation sans en parler à l’intervenant

Présent sur un événement la semaine dernière, je vais voir comme à mon habitude la personne en charge de la projection des présentations pour m’assurer qu’il a bien tout et qu’il n’a pas de question. En discutant cinq avec lui, à un moment il me dit :

« Il y avait des animations compliquées, j’ai retiré toutes les durées prédéfinies, de toutes façons ça ne marche jamais ».

Gros blanc. Les intervenants s’étaient soigneusement préparés pour se caler sur un timing précis.

On ne change pas le fonctionnement d'une présentation sans en parler à l'intervenant avant.

Si vous travaillez sur la présentation de quelqu’un d’autre, s’il vous plaît ne changez pas les durées des animations sans demander la permission au présentateur avant. Votre responsabilité est de vous assurer que la présentation fonctionne correctement telle que le présentateur l’a fournie, et si nécessaire de l’avertir si vous pensez qu’il a fait une erreur ou quelque chose qui ne fonctionnera pas. Mais ce n’est en aucun cas de décider à la place du présentateur comment il doit présenter. Si vous le faites et qu’un présentateur important se plaint (qu’il soit réellement important ou non), vous allez avoir pas mal d’ennuis que vous auriez pu facilement éviter. J’ai déjà reçu un email incendiaire de la part des organisateurs d’une conférence parce que un intervenant étranger très important s’était plaint que j’avais « cassé » sa présentation ; en fait elle s’affichait mal parce qu’il l’avait regardée sur son iPhone au lieu de l’ouvrir dans PowerPoint, mais c’est toujours des moments délicats à gérer.

Et pour les animations que s’est-il finalement passé ? Elles n’étaient pas trop compliquées à refaire, et chaque groupe qui avait des durées prédéfinies précises a travaillé avec le graphiste pour les rétablir. Mais ce moment de panique de dernière minute aurait pu être facilement évité en appliquant les conseils de ce billet. De plus certaines animations compliquées auraient pu être impossibles à reconstruire correctement.

Articles liés

Contrôler PowerPoint avec un contrôleur MIDI

Keyboard Maestro fait partie du top 5 des programmes que j’utilise tout le temps pour simplifier ou automatiser mon travail sur Mac. J’ai déjà donné quelques exemples d’actions possibles dans cet article. Depuis la semaine dernière Keyboard Maestro 8 est disponible. Je ne vais pas lister toutes les nouveautés ici, elles sont trop nombreuses, pour cela rendez vous directement sur la page officielle (en anglais).

Je vais juste évoquer l’amélioration de la partie MIDI ; il est désormais possible de déclencher des actions à partir d’un contrôleur MIDI.

J’ai un vieux contrôleur MIDI indestructible qui ressemble à un truc sorti d’un film de SF des années 60. Normalement je m’en sers pour contrôler les amplis virtuels de guitare, mais pour la démo je l’ai utilisé pour contrôler… PowerPoint ! Et pourquoi pas après tout ? Lorsqu’on tourne le bouton 1 la transparence de l’objet change. Le bouton 2 change l’épaisseur du trait. Le bouton 3 change la taille de la police de caractères, etc. Lorsqu’on appuie sur le bouton au dessus cela applique le réglage à l’objet sélectionné (par exemple si le bouton est réglé sur une taille de police 24, appuyer sur le bouton va mettre le texte sélectionné en taille 24).

Controleur MIDI

L’avantage de ce contrôleur MIDI est d’utiliser des boutons à rotation « infinie », par opposition aux boutons qui se bloquent sur la butée lorsqu’ils ont atteint leur valeur minimum ou maximum. Cela permet de définir la valeur de départ du bouton de manière logicielle. La petite barre sur l’écran LCD représente la valeur courante du bouton.

Ça demande un peu de bricolage pour tout faire fonctionner, mais une fois au point c’est très rigolo de pouvoir régler les paramètres de PowerPoint avec des molettes. Le gain de productivité est (très) discutable, mais je l’ai fait pour montrer les possibilités du contrôle MIDI de Keyboard Maestro 8.

Articles liés

Trier automatiquement ses projets par statut

Comment trier ses projets dans OmniFocus ? Professionnel vs. personnel ? Par priorité ? Par date d’échéance ? Personnellement je les trie par statut. Si vous regardez l’image ci-dessous vous verrez que j’ai des dossiers nommés « active » (actifs), « stalled » (bloqué), « waiting for » (en attente), etc.

Projets OmniFocus

Pourquoi ai-je choisi de trier mes projets de cette manière ? Parce que cela me permet d’identifier en un coup d’œil les projets sur lesquels je dois travailler, ceux que je dois débloquer, ceux qui sont en attente de quelque chose, etc.

Évidemment cette organisation est un peu pénible s’il faut trier manuellement les projets dans les dossiers en fonction de l’évolution de leur statut. C’est pourquoi j’ai écrit un script AppleScript appelé « housekeeping » qui va classer chaque projet automatiquement dans le bon dossier selon son statut. Vous trouverez le code du script ci-dessous. Je l’ai fait un peu à l’arrache, c’est loin d’être un exemple de code propre, et il faudra sûrement l’adapter un peu pour qu’il fonctionne chez vous, néanmoins j’espère qu’il peut vous aider si vous voulez faire quelque chose de similaire.

Ce script fait également d’autres choses : il définit la prochaine date de revue de manière plus « intelligente » : par exemple si la prochaine date de revue tombe un week-end il va déplacer la date de revue au lundi suivant, il va définir la fréquence de revue selon que le projet soit actif ou en attente, etc.

J’ai codé « en dur » certaines chaînes de caractères comme un gros goret, donc pour que le script fonctionne vous devez absolument avoir des dossiers nommés “active”, “stalled”, “waiting for”, “deferred”, “on hold”, “completed”, “dropped”, “templates” et un contexte nommé “Waiting for”. L’alternative étant d’éditer les chaînes de caractères dans le script utiliser d’autres noms. Il y a peut-être d’autres chose qu’il faudra vérifier pour qu’il fonctionne correctement. Pour rappel, ce genre de script est quasi impossible à débugger dans l’éditeur de scripts fourni en standard par Apple, à la place j’utilise Script Debugger de Late Night Software, un outil indispensable pour tout AppleScripter qui se respecte.

Et concernant le débat tabulations contre espaces, l’exemple ici utilise des espaces parce que les tabulations prenaient trop de place, mais mon script original utilise bien des tabulations !

Enfin il y a quelques bouts de code que j’ai piqué à gauche et à droite sur internet, mais je n’arrive plus à retrouver où, donc je tiens à m’en excuser auprès de leurs auteurs originaux. Les développeurs un peu expérimentés les reconnaîtront sûrement, parce que le style du code est clairement différent.

Attention : je ne suis pas responsable des problèmes que peut occasionner ce script, utilisez-le à vos risques et périls !!!

(*
  This script does the following:
  1. Sort projects in folders based on status
    - flagged
    - active
    - stalled
    - waiting for
    - defered
    - completed
    - dropped
  2. Set review date to now for:
    - Projects modified since last run
    - Projects moved

  3. Set review interval to weekly for:
    - Projects that are active, stalled or waiting for

  4. A few other things
*)

property fiveMinutes : 300
property oneDay : 86400
property sevenDays : 604800
property fourteenDays : 1209600
property twentyoneDays : 1814400
property sixtyDays : 51840000
property twelveWeeks : 7257600
property changeGracePeriod : 0 -- 240
property contextWaitingFor : {"waiting for"}
property contextStalled : {"object", "reference"}
-- if script was never run set last run to 5 minutes ago by default
property lastRun : (current date) - fiveMinutes
property putOnHoldIfWaitingForTooLong : sixtyDays

global theFlaggedFolder
global theActiveFolder
global theStalledFolder
global theWaitingForFolder
global theDeferredFolder
global theOnHoldFolder
global theCompletedFolder
global theDroppedFolder
global theTemplateFolder

global theWaitingForContext

property scriptSuiteName : "Projects Housekeeping"

tell application "OmniFocus"
  tell front document
    
    compact
    try
      -- set theFlaggedFolder to (first folder whose name is "flagged")
      set theActiveFolder to (first folder whose name is "active")
      set theStalledFolder to (first folder whose name is "stalled")
      set theWaitingForFolder to (first folder whose name is "waiting for")
      set theDeferredFolder to (first folder whose name is "deferred")
      set theOnHoldFolder to (first folder whose name is "on hold")
      set theCompletedFolder to (first folder whose name is "completed")
      set theDroppedFolder to (first folder whose name is "dropped")
      set theTemplateFolder to (first folder whose name is "templates")
      
      set theWaitingForContext to (first flattened context whose name is "Waiting For")
      
      set will autosave to false
      -- set selected sidebar tab to
      set projectsMoved to my moveActiveProjects(it, {})
      set projectsMoved to projectsMoved or my moveNonActiveProjects(it)
      set will autosave to true
    on error errText number errNum
      set will autosave to true
      display dialog "Error: " & errNum & return & errText
      return
    end try
    if projectsMoved is true then
      set msg to "Please review projects."
      my notify("Did some housekeeping!", msg)
    else
      set msg to "I had nothing to do."
    end if
  end tell
end tell
set lastRun to (current date)



on moveNonActiveProjects(theContainer)
  set projectsMoved to false
  using terms from application "OmniFocus"
    set theProjects to every flattened project of theContainer whose status is on hold ¬
      and singleton action holder is false
    repeat with aProject in theProjects
      if completed by children of aProject is true then
        -- do not complete projects when all tasks are done to avoid accidental completion
        set completed by children of aProject to false
      end if
      set theResult to my reviewIfTaskModified(aProject)
      if theResult is equal to 0 then
        my reviewMonthly(aProject)
      end if
      set isProjectMoved to my moveProject(aProject, theOnHoldFolder)
      set projectsMoved to projectsMoved or isProjectMoved
    end repeat
    
    set theProjects to every flattened project of theContainer whose status is done ¬
      and singleton action holder is false
    repeat with aProject in theProjects
      if completed by children of aProject is true then
        -- do not complete projects whene all tasks are done to avoid accidental completion
        set completed by children of aProject to false
      end if
      -- No need to change review interval
      set isProjectMoved to my moveProject(aProject, theCompletedFolder)
      set projectsMoved to projectsMoved or isProjectMoved
    end repeat
    
    set theProjects to every flattened project of theContainer whose status is dropped ¬
      and singleton action holder is false
    repeat with aProject in theProjects
      if completed by children of aProject is true then
        -- do not complete projects when all tasks are done to avoid accidental completion
        set completed by children of aProject to false
      end if
      -- No need to change review interval
      set isProjectMoved to my moveProject(aProject, theDroppedFolder)
      set projectsMoved to projectsMoved or isProjectMoved
    end repeat
  end using terms from
  return projectsMoved
end moveNonActiveProjects



on moveActiveProjects(theContainer)
  set projectsMoved to false
  --  log "Executing Housekeeping Script"
  using terms from application "OmniFocus"
    set theProjects to every flattened project of theContainer whose status is active ¬
      and singleton action holder is false
    set projectsMoved to my moveActiveProjectsProjects(theProjects)
  end using terms from
  return projectsMoved
end moveActiveProjects



on moveActiveProjectsProjects(theProjects)
  
  using terms from application "OmniFocus"
    set projectsMoved to false
    repeat with aProject in theProjects
      set projectContainer to container of aProject
      if (class of projectContainer is not folder or (class of projectContainer is folder ¬
        and projectContainer is not hidden)) then
        
        if folder of aProject is not theTemplateFolder then
          
          if completed by children of aProject is true then
            set completed by children of aProject to false
          end if
          
          my reviewIfTaskModified(aProject)
          
          -- Checks if there is a next task
          -- If yes, then get context of next task
          set theNextTask to next task of aProject
          set isNoNextTask to false
          set theNextTaskContextName to "****"
          set isAlreadyProcessed to false
          set isDeferredNextTask to false
          
          if theNextTask is missing value then
            set theActiveTasks to ¬
              (every flattened task of aProject whose completed is false ¬
                and number of tasks is equal to 0)
            if (count of theActiveTasks) is greater than or equal to 1 then
              set theActiveTask to item 1 of theActiveTasks
              if theActiveTask is not missing value then
                if defer date of theActiveTask is not missing value then
                  if defer date of theActiveTask is greater than (current date) then
                    set isDeferredNextTask to true
                  else
                    set theNextTask to theActiveTask
                    set theNextTaskContextName to name of context of theNextTask
                  end if
                else
                  set theNextTask to theActiveTask
                  set theNextTaskContextName to name of context of theNextTask
                end if
              else
                set isNoNextTask to true
              end if
            else -- project has no next tasks
              set isNoNextTask to true
              set theWaitingForTasks to (every flattened task of aProject whose completed is false)
              set isNoNextTask to true
              repeat with theWaitingForTask in theWaitingForTasks
                if context of theWaitingForTask is equal to theWaitingForContext then
                  set theNextTask to theWaitingForTask
                  set isNoNextTask to false
                  if context of theNextTask is not missing value then
                    set theNextTaskContextName to name of context of theNextTask
                  end if
                  exit repeat
                end if
              end repeat
              
            end if
          else
            -- If the next task is the project itself, consider there is no task left.
            if id of theNextTask is equal to id of root task of aProject then
              set isNoNextTask to true
            else
              set isNoNextTask to false
              if context of theNextTask is not missing value then
                set theNextTaskContextName to name of context of theNextTask
              end if
            end if
          end if
          
          -- 
          -- Process DEFERRED projects
          -- 
          if isAlreadyProcessed is false then
            if defer date of aProject is not missing value then
              set theCurrentDate to current date
              set theCurrentDate to theCurrentDate - (theCurrentDate's time)
              -- Second condition is to avoid the project being marked for review again and again 
              -- if review date is today
              if defer date of aProject is greater than or equal to my tomorrow() then
                my setNextReviewDate(aProject, defer date of aProject)
                set isProjectMoved to my moveProject(aProject, theDeferredFolder)
                set projectsMoved to projectsMoved or isProjectMoved
                set isAlreadyProcessed to true
              end if
            end if
          end if
          if isAlreadyProcessed is false then
            if isDeferredNextTask then
              if defer date of theActiveTask is greater than or equal to my tomorrow() then
                my setNextReviewDate(aProject, defer date of theActiveTask)
                set isProjectMoved to my moveProject(aProject, theDeferredFolder)
                set projectsMoved to projectsMoved or isProjectMoved
                set isAlreadyProcessed to true
              end if
            end if
          end if
          
          --
          -- Process WAITING FOR projects
          --
          if isAlreadyProcessed is false then
            if theNextTaskContextName is in contextWaitingFor then
              --
              -- ...then it is waiting for but if waiting for more than twenty one days...
              --
              set theTimeDifference to (current date) - (modification date of theNextTask)
              if theTimeDifference is greater than putOnHoldIfWaitingForTooLong ¬
                and putOnHoldIfWaitingForTooLong is not equal to 0 then
                --
                -- ...then we were patient enough, change status and move it to on hold
                --
                my reviewDaily(aProject)
                my setStatus(aProject, on hold)
                set isProjectMoved to my moveProject(aProject, theOnHoldFolder)
                set projectsMoved to projectsMoved or isProjectMoved
                set isAlreadyProcessed to true
              else
                --
                -- ...else it's really waiting for
                --
                if theTimeDifference is greater than sevenDays then
                  -- waiting for more than seven days? Review weekly
                  my reviewWeekly(aProject)
                else
                  -- waiting for less than one week? Review daily
                  my reviewDaily(aProject)
                end if
                set isProjectMoved to my moveProject(aProject, theWaitingForFolder)
                set projectsMoved to projectsMoved or isProjectMoved
                set isAlreadyProcessed to true
              end if
            end if
          end if
          
          --
          -- Process STALLED projects
          -- 
          if isAlreadyProcessed is false then
            if isNoNextTask is true or theNextTaskContextName is in contextStalled then
              my reviewDaily(aProject)
              set isProjectMoved to my moveProject(aProject, theStalledFolder)
              set projectsMoved to projectsMoved or isProjectMoved
              set isAlreadyProcessed to true
            end if
          end if
          
          --
          -- Process ACTIVE projects
          --
          if isAlreadyProcessed is false then
            my reviewDaily(aProject)
            if folder of aProject is not theActiveFolder then
              set isProjectMoved to my moveProject(aProject, theActiveFolder)
              set projectsMoved to projectsMoved or isProjectMoved
              set isAlreadyProcessed to true
            end if
          end if
          
        end if
      end if
      
    end repeat
  end using terms from
  return projectsMoved
end moveActiveProjectsProjects

(*
Changes the status of a project and logs it.
*)
on setStatus(aProject, aStatus)
  tell application "OmniFocus"
    tell front document
      if status of aProject is not aStatus then
        set status of aProject to aStatus
        log "Changed status of project: " & (name of aProject)
      end if
    end tell
  end tell
end setStatus

(*
  Moves a Project to a new folder
*)
on moveProject(aProject, aFolder)
  set projectMoved to false
  tell application "OmniFocus"
    tell front document
      if folder of aProject is not aFolder then
        my reviewNow(aProject)
        move aProject to (beginning of sections of aFolder)
        set projectMoved to true
        log "Moved project: " & (name of aProject)
      end if
    end tell
  end tell
  return projectMoved
end moveProject

(*
  Mark a project for review if a task has been modified
*)
on reviewIfTaskModified(aProject)
  tell application "OmniFocus"
    tell front document
      set theTasks to (every flattened task of aProject ¬
        whose modification date is greater than lastRun and completed is false)
      if (count of theTasks) is greater than 0 then
        my reviewNow(aProject)
        return 1
      else
        return 0
      end if
    end tell
  end tell
end reviewIfTaskModified

(*
  Gets tomorrow, midnight.
*)
on tomorrow()
  copy (current date) to theDate
  return (theDate + oneDay - (theDate's time))
end tomorrow

on reviewNow(aProject)
  set theNextReview to current date
  -- note: do not change review interval in this case
  my setNextReviewDate(aProject, theNextReview)
end reviewNow

on reviewDaily(aProject)
  set theNextReview to my tomorrow()
  tell application "OmniFocus"
    tell front document
      set _ri to {unit:(day), steps:(1), fixed:(false)}
      my setReviewInterval(aProject, _ri)
      my setNextReviewDate(aProject, theNextReview)
    end tell
  end tell
end reviewDaily

on reviewWeekly(aProject)
  -- Set the next weekly review to next Monday
set theNextReview to ¬
	DateOfThisInstanceOfThisWeekdayBeforeOrAfterThisDate(current date, Monday, 1)
	  
  using terms from application "OmniFocus"
    set _ri to {unit:(week), steps:(1), fixed:(false)}
  end using terms from
  tell application "OmniFocus"
    tell front document
      my setReviewInterval(aProject, _ri)
      my setNextReviewDate(aProject, theNextReview)
    end tell
  end tell
end reviewWeekly

(*
  Sets the next review date to the next first Monday of a Month
  (this month if first Monday not already passed)
  (next month if first Monday already passed)
*)
on reviewMonthly(aProject)
  copy (current date) to theNextReview
	if (weekday of theNextReview is Monday) ¬
	and (day of theNextReview ≤ 7) and (theNextReview > (current date)) then
    -- do nothing because next review is already first Monday and in the future
  else
    set theNextReview's day to 32
    set theNextReview's day to 1
    -- That stuff below is to always set the monthly review on the first Monday of the Month
    set dateOffset to {1, 0, 6, 5, 4, 3, 2}
    set theOffset to item ((weekday of theNextReview) as integer) of dateOffset
    set theNextReview's day to 1 + theOffset
    set theNextReview to theNextReview - (theNextReview's time)
    tell application "OmniFocus"
      tell front document
        set _ri to {unit:(month), steps:(1), fixed:(false)}
        my setReviewInterval(aProject, _ri)
        my setNextReviewDate(aProject, theNextReview)
      end tell
    end tell
  end if
end reviewMonthly

on setReviewInterval(aProject, _ri)
  tell application "OmniFocus"
    tell front document
      if review interval of aProject is not equal to _ri then
        set review interval of aProject to _ri
        log "Changed review interval: " & (name of aProject)
      end if
    end tell
  end tell
end setReviewInterval

(*
  Sets the review date for the project to the date specified, but only if:
  - the project's review date is greater than today (is in the future)
  - the project's review date is not already equal to the new review date
  If the review date is a Saturday or Sunday, sets it to the next Monday
*)
on setNextReviewDate(aProject, aDate)
  tell application "OmniFocus"
    tell front document
      -- Skip Saturdays and Sundays, use Monday instead, and remove Date's time.
      set aDate to (my skipWeekends(aDate)) - (aDate's time)
      -- Only change review date if it is greater than now and is different from the new date
      if next review date of aProject is greater than (current date) ¬
        and next review date of aProject is not equal to aDate then
        set next review date of aProject to aDate
        log "Changed review date: " & (name of aProject)
      end if
    end tell
  end tell
end setNextReviewDate

on skipWeekends(aDate)
  if weekday of aDate is Saturday then
    set aDate to aDate + 2 * oneDay
  else if weekday of aDate is Sunday then
    set aDate to aDate + oneDay
  end if
  return aDate
end skipWeekends

on DateOfThisInstanceOfThisWeekdayBeforeOrAfterThisDate(d, w, i) -- returns a date
  -- Keep an note of whether the instance value *starts* as zero
  set instanceIsZero to (i is 0)
  -- Increment negative instances to compensate for the following subtraction loop
  if i < 0 and d's weekday is not w then set i to i + 1
  -- Subtract a day at a time until the required weekday is reached
  repeat until d's weekday is w
    set d to d - days
    -- Increment an original zero instance to 1 if subtracting from Sunday into Saturday 
    if instanceIsZero and d's weekday is Saturday then set i to 1
  end repeat
  -- Add (adjusted instance) * weeks to the date just obtained and zero the time
  d + i * weeks - (d's time)
end DateOfThisInstanceOfThisWeekdayBeforeOrAfterThisDate

(*
  Uses Notification Center to display a notification message.
  theTitle – a string giving the notification title
  theDescription – a string describing the notification event
*)
on notify(theTitle, theDescription)
  display notification theDescription with title scriptSuiteName subtitle theTitle
end notify

Articles liés

Non, je n’automatise pas tout !

Vous le savez, je suis un grand partisan de l’automatisation pour économiser du temps. Pourtant ce n’est pas vrai pour tout. Par exemple je fais mon café du matin à l’Aeropress, une méthode assez originale pour préparer le café. Chaque matin je mouds les grains de café à la main, je fais bouillir l’eau et j’utilise ensuite l’Aeropress pour faire le café. La solution automatique serait d’utiliser une machine à expresso à dosettes. Mais le problème c’est que je trouve que les cafés faits avec une machine à expresso sont trop courts. De plus pour le matin je trouve le goût du café fait à l’Aeropress plus doux et plus savoureux.

Et lorsque je travaille le bois, le seul appareil électrique que j’utilise est une foreuse. Je fais tout le reste à la main. C’est (beaucoup) plus lent et fatiguant, mais c’est bien plus gratifiant, même si en raison de mes compétences très limitées le résultat n’est pas toujours à la hauteur !

C’est également ce que je fais lorsque je prépare un gâteau. Je n’utilise aucun appareil électrique, je fais tout à la main. De nouveau je trouve que le résultat est bien plus gratifiant, même si au final le goût est exactement le même.

Le point commun de toutes ces tâches manuelles ?

  • Je n’ai pas besoin qu’elles soient “productives”,
  • Je ne produits que des quantités très limitées,
  • Les faire à la main me détend.

L’automatisation c’est bien, mais parfois prendre le temps de bien faire les choses est tellement plus gratifiant.

Articles liés