How close can a bipedal (chained) eidolon get to a human-like appearance?

So I asked a similar question here and that was confirmed. So I want to extend it. Since an eidolon can get close enough to a human pass a disguise check to pretend to be one, just how close can it get? Looking like it’s made of clay or porcelain could be called roughly human but anyone who takes a long hard look is going to tell the difference unless it’s wearing full body armor or something similar.

The rules for the eidolon’s appearance read as follows.

The eidolon’s physical appearance is up to the summoner, but it always appears as some sort of fantastical creature. This control is not fine enough to make the eidolon appear like a specific creature. The eidolon also bears a glowing rune that is identical to a rune that appears on the summoner’s forehead as long as the eidolon is summoned. While this rune can be hidden through mundane means, it cannot be concealed through magic that changes appearance, such as alter self or polymorph (although invisibility does conceal it as long as the spell lasts).

Biped Starting Statistics

Size Medium; Speed 30 ft.; AC +2 natural armor; Saves Fort (good), Ref (bad), Will (good); Attack 2 claws (1d4); Ability Scores Str 16, Dex 12, Con 13, Int 7, Wis 10, Cha 11

Free Evolutions

Claws, limbs (arms), limbs (legs).

Bodyguard Source: PZO1117

The eidolon looks like a humanoid warrior. The natural armor of a Bodyguard eidolon appears to be a suit of metal plate, though this armor is actually part of the eidolon’s body. Bodyguard eidolons are normally trained in a variety of dangerous weapons.

11 points: Base Form biped; Primary Evolutions improved natural armor, weapon training; Secondary Evolutions ability increase (Strength), fast healing, weapon training (martial).

An unchained Eidolon can do that via a few subtypes ancestor and angel being prime examples which is why I specified chained which from what I’ve heard is a massive upgrade from unchained.

Ancestor source: PZO9473 Whether created by bonding with the soul of a petitioner that was the summoner’s ancestor in life or calling upon the impressions of such a soul left behind on the Ethereal Plane or the Akashic Record, ancestor eidolons are outsiders cast in the mold of mortals, and exhibit extraordinary skill and talent. They usually appear as idealized versions of the bodies they possessed while still alive, but distinctive and proud. Ancestor eidolons lend whatever aid they can to their summoner, who typically has some form of familial connection with the eidolon, be it by blood, honor, or devotion.

Angel Hailing from the higher planes, angel eidolons are creatures of exquisite beauty. They usually appear in idealized humanoid forms, with smooth skin, shining hair, and bright eyes. Angel eidolons are impeccably honorable, trustworthy, and diplomatic, but they do not shy away from confrontation when facing off against evil and its minions.

Can a bipedal (chained) eidolon pass itself off as a human or similar race?

So I saw the bodyguard suggested build in the SRD and thought “That sounds awesome, but you know what will make it even better? If it were a shinobi.” Yes, I know very anime that’s just how I am. The rune is an obvious problem but giving them a fox mask would build on the anime field and hide the rune as per the rules (see below). Can a bipedal take on a human form or does it have to be a monstrous humanoid or something similar. Maybe an Aasimar or a Humanoid Fey? If not is there a way to accomplish this with feats or archetypes.

The SRD says

The eidolon’s physical appearance is up to the summoner, but it always appears as some sort of fantastical creature. This control is not fine enough to make the eidolon appear like a specific creature. The eidolon also bears a glowing rune that is identical to a rune that appears on the summoner’s forehead as long as the eidolon is summoned. While this rune can be hidden through mundane means, it cannot be concealed through magic that changes appearance, such as alter self or polymorph (although invisibility does conceal it as long as the spell lasts).

Biped Starting Statistics

Size Medium; Speed 30 ft.; AC +2 natural armor; Saves Fort (good), Ref (bad), Will (good); Attack 2 claws (1d4); Ability Scores Str 16, Dex 12, Con 13, Int 7, Wis 10, Cha 11

Free Evolutions

Claws, limbs (arms), limbs (legs).

Bodyguard Source: PZO1117

The eidolon looks like a humanoid warrior. The natural armor of a Bodyguard eidolon appears to be a suit of metal plate, though this armor is actually part of the eidolon’s body. Bodyguard eidolons are normally trained in a variety of dangerous weapons.

11 points: Base Form biped; Primary Evolutions improved natural armor, weapon training; Secondary Evolutions ability increase (Strength), fast healing, weapon training (martial).

An unchained Eidolon can do that via the Acesstor Subtype and many others which is why I specified chained which from what I’ve heard is a massive upgrade from unchained.

Ancestor source: PZO9473 Whether created by bonding with the soul of a petitioner that was the summoner’s ancestor in life or calling upon the impressions of such a soul left behind on the Ethereal Plane or the Akashic Record, ancestor eidolons are outsiders cast in the mold of mortals, and exhibit extraordinary skill and talent. They usually appear as idealized versions of the bodies they possessed while still alive, but distinctive and proud. Ancestor eidolons lend whatever aid they can to their summoner, who typically has some form of familial connection with the eidolon, be it by blood, honor, or devotion.

How much times the strength modifier does a chained barbarian add when making a bite using Animal Fury?

The assumption is bite is the only attack the barbarian makes during the turn, and the barbarian has no other natural attacks. I seem to get three different answers on this:

The barbarian adds 0.5x the strength modifier. This is because the rules on Animal Fury state that “If the bite hits, it deals 1d4 points of damage (assuming the barbarian is Medium; 1d3 points of damage if Small) plus half the barbarian’s Strength modifier.”

The barbarian adds 1x the strength modifier. This is because the 19 STR cannibal from the gamemastery guide has its bite damage listed as 1d4+4, which is consistent with this.

The barbarian adds 1.5x the strength modifier. This is because a bite is a primary natural attack, and the natural attack rules state that “If a creature has only one natural attack, it is always made using the creature’s full base attack bonus and adds 1-1/2 times the creature’s Strength bonus on damage rolls.”

So which one is it?

XSS chained with CSRF = Stored XSS?

I have recently heard that XSS + CSRF = stored XSS. I didn’t think too much about it at the time, but now it’s bugging me, because it doesn’t make too much sense.

I would say that it can stand true, if the XSS was “self-stored XSS” for which CSRF is used to get rid of the “self” part.

Other than that, I don’t see any other potential way for the aforementioned equation to be true. Is there another case that I miss?

Prevent token sharing: chained single-use tokens VS a designated invalidation feature


Situation:

  • A Client is requesting a resource from a Host multiple times, usually with minutes or hours between requests.
  • The Client has a signed, verifiable token, which we’ll call a Receipt, that asserts that they should be allowed to access the resource. (The Receipt will eventually expire, say at the end of the month.)
  • The Host has no way of knowing (and should have no way of knowing) who the Client is beyond the fact that a given receipt is being reused.

Problem:

Receipts cost money. (We’re building a micro-transaction service; so they cost ~0.10USD) We don’t want users (Clients) posting their Receipts online for public use, or otherwise sharing Receipts. It is not critical that nobody can share Receipts, but sharing Receipts should generally be inconvenient, and hypothetical systems for sharing receipts shouldn’t scale well.

Note that in this model a “user” may have multiple “Clients” running on different machines, and will share Receipts among their Clients.

Proposed Solutions:

  1. Have the Client create a public/private key pair for each receipt (or however often the Client wants to). The public key will be submitted with the Receipt, and whenever the Host sees a given Receipt for the first time they’ll store the accompanying public key so they can verify that future submissions came from the same person (even though they don’t know who that is).
    • cons: This just moves the “secret that shouldn’t be shared” from the Receipt to the private key.
    • pros: A private key really is easier to keep secret, in particular because, while the Receipt is sent to the Host, the private key never leaves the Client’s control.
  2. Have the Host give the Client a single-use Token (as part of their normal response) to be included with their next submission of a given Receipt. These Tokens can be quite small. Re-submission of a Receipt (even once) without the expected Token is evidence that the receipt has been shared.
    • cons: This will make both systems (Client and Host) harder to implement. It’s convoluted and error-prone. Because Clients owned by a single user will share Receipts, some “false positives” are inevitable. Furthermore, sharing Receipts inappropriately is still possible using a system not too different from how well-behaving users will share Receipts among their devices. In this sense this solution relies on incompetent members of they hypothetical sharing pool accidentally violating the Token chain.
    • pros: Building a sharing pool would be relatively difficult, and as a pool scaled up in members and usage it would become increasingly non-performant (because of locking) or increasingly likely to break Receipts (because they’d been noticed as shared). Additionally, a “good samaritan” in the sharing pool would be able to break the shared Receipts by intentionally violating the Token chains.
  3. Give “good samaritans” a specific function for invalidating receipts.
    • cons: Does nothing to directly prevent sharing, it relies entirely on the idea that any hypothetical sharing pool would either not scale, or eventually be infiltrated by some kind of defector.
    • pros: It’s much easier to implement. Additionally, if combined with #1, then the Host would have a signed invalidation request they could present if their decision to reject subsequent submissions of that Receipt were ever challenged.

Originally I was planing on doing #1 and #2,
but having thought about it for a couple days I’m thinking #1 and #3 (or maybe just #3) would be easier and good enough.

Do people have suggestions for any (combination) of the above solutions, or other solutions I haven’t listed?

Are there important angles I’ve overlooked?

How to configure two Dell U2415’s monitors daisy chained over displayport with Nvidia Titan X

I am working on a fresh install of Ubuntu 18.04.2 LTS desktop with the default gnome desktop. I installed the nvidia proprietary driver nvidia-driver-390 from Software & Updates -> Additional Drivers.

When the desktop starts, it only shows on the primary monitor. I have to run

xset dpms force off 

to force the monitors into sleep state and then move the mouse to wake them up and both monitors become active. However, one of the monitors runs at a very low resolution (640×480) while the other runs at the full resolution (1920×1200). Here’s a screenshot of the Nvidia X Settings. Nvidia X settings

The first monitor is detected as “NVIDIA” with resolution 640×480 (the only options under resolution are Off, Auto, and 640×480). The second monitor is correctly detected as “DELL U2415” with resolution 1920×1200. Here is the output of the xrandr command. DP-0.8 is the first monitor in the daisy chain and DP-0.1 is the second. I have enabled displayport 1.2 on the first monitor and disabled on the 2nd monitor.

    Screen 0: minimum 8 x 8, current 2560 x 1200, maximum 16384 x 16384 DVI-I-0 disconnected (normal left inverted right x axis y axis) DP-0.1 connected 1920x1200+640+0 (normal left inverted right x axis y axis) 518mm x 324mm    1920x1200     59.95*+  59.88      1920x1080     60.00    59.94    50.00    29.97    25.00    23.98      1600x1200     60.00      1280x1024     75.02    60.02      1280x720      60.00    59.94    50.00      1152x864      75.00      1024x768      75.03    60.00      800x600       75.00    60.32      720x576       50.00      720x480       59.94      640x480       75.00    59.94    59.93   DP-0.8 connected primary 640x480+0+0 (normal left inverted right x axis y axis) 0mm x 0mm    640x480       59.94*+ DVI-I-1 disconnected (normal left inverted right x axis y axis) HDMI-0 disconnected (normal left inverted right x axis y axis) DP-0 disconnected (normal left inverted right x axis y axis) DP-1 disconnected (normal left inverted right x axis y axis) DP-2 disconnected (normal left inverted right x axis y axis) DP-3 disconnected (normal left inverted right x axis y axis) DP-4 disconnected (normal left inverted right x axis y axis) DP-5 disconnected (normal left inverted right x axis y axis) DP-0.1.8 disconnected (normal left inverted right x axis y axis) 

At this point, there was no /etc/X11/xorg.conf file or monitors.xml file anywhere on the machine. I saved the X configuration file from Nvidia X Settings application. The saved /etc/X11/xorg.conf file is as follows.

# nvidia-settings: X configuration file generated by nvidia-settings # nvidia-settings:  version 390.77  (buildd@lcy01-amd64-022)  Thu Sep  6 07:51:39 UTC 2018  Section "ServerLayout"     Identifier     "Layout0"     Screen      0  "Screen0" 0 0     InputDevice    "Keyboard0" "CoreKeyboard"     InputDevice    "Mouse0" "CorePointer"     Option         "Xinerama" "0" EndSection  Section "Files" EndSection  Section "Module"     Load           "dbe"     Load           "extmod"     Load           "type1"     Load           "freetype"     Load           "glx" EndSection  Section "InputDevice"     # generated from default     Identifier     "Mouse0"     Driver         "mouse"     Option         "Protocol" "auto"     Option         "Device" "/dev/psaux"     Option         "Emulate3Buttons" "no"     Option         "ZAxisMapping" "4 5" EndSection  Section "InputDevice"     # generated from default     Identifier     "Keyboard0"     Driver         "kbd" EndSection  Section "Monitor"     # HorizSync source: edid, VertRefresh source: edid     Identifier     "Monitor0"     VendorName     "Unknown"     ModelName      "NVIDIA"     HorizSync       31.5 - 31.5     VertRefresh     60.0     Option         "DPMS" EndSection  Section "Device"     Identifier     "Device0"     Driver         "nvidia"     VendorName     "NVIDIA Corporation"     BoardName      "GeForce GTX TITAN X" EndSection  Section "Screen"     Identifier     "Screen0"     Device         "Device0"     Monitor        "Monitor0"     DefaultDepth    24     Option         "Stereo" "0"     Option         "nvidiaXineramaInfoOrder" "DFP-2.8"     Option         "metamodes" "DP-0.8: nvidia-auto-select +0+0, DP-0.1: nvidia-auto-select +640+0"     Option         "SLI" "Off"     Option         "MultiGPU" "Off"     Option         "BaseMosaic" "off"     SubSection     "Display"         Depth       24     EndSubSection EndSection 

I see only one “monitor” section in this xorg.config. Why doesn’t it list the 2nd monitor?

In any case, how can I have the nvidia card properly detect both monitors as Dell U2415 along with the 1920×1200 resolution?

chained conditional mapping – `ifDefined` method

Is there a more concise way of conditionally mapping over a value like in:

val userName: Option[String] = Some("Bob") val address: Option[String] = Some("Planet Earth")  val dbQuery = new Query()  val afterUserName =    userName.map(u => dbQuery.copy(_.userName = u))     .getOrElse(dbQuery)  val modifiedQuery =    address.map(a => afterUserName.copy(_.address = a))     .getOrElse(afterUserName) 

I wish there was an ifDefined method available on all types like in the following block. This removes the .getOrElse(...) call.

dbQuery   .ifDefined(userName)((d, u) => d.copy(d.userName = u)   .ifDefined(address)((d, a) => d.copy(d.address = a) 

Chained Many To Many Field não retorna valores

Segue abaixo imagem da tela de cadastro onde deveria aparecer opções para escolhas Ao selecionar Feição deveria aparecer opções nos campos Possíveis Causas e Prováveis consequências

A baixo imagem contendo as opções que deveriam aparecer na imagem acima As opções selecionadas deveriam estar presentes na tela anterior

segue o código do model.py

from django.contrib.gis.db import models from djgeojson.fields import PointField from django.contrib.gis.geos import Point from django.contrib.gis.geos import GEOSGeometry from django.contrib.gis.gdal import SpatialReference, CoordTransform # from bdg import models as bdg_models from django.contrib.gis.measure import D import django_tables2 as tables from sorl.thumbnail import ImageField from rest_framework import serializers from smart_selects.db_fields import ChainedManyToManyField from django.contrib import messages from django.shortcuts import render from .thumbs import ImageWithThumbsField from sorl_thumbnail_serializer.fields import HyperlinkedSorlImageField from drf_dynamic_fields import DynamicFieldsMixin from django.core.validators import FileExtensionValidator import zipfile  class Causa(models.Model):     nome = models.CharField(max_length=250, null=True, blank=True)      def __str__(self):         return self.nome  class Consequencia(models.Model):     nome = models.CharField(max_length=250, null=True, blank=True)      def __str__(self):         return self.nome  class Feicao(models.Model):     # Opcoes Tipo     acesso_irregular = "Acesso irregular"     acumulo_sedimentos_pista = "Acumulo de sedimentos sobre a pista"     alagamento = "Alagamento"     assoreamento = "Assoreamento"     atropelamento_animais_silvestres = "Atropelamento de animais silvestres"     deslizamento = "Deslizamento"     erosao = "Erosão "     estrutura_abandonada = "Estrutura abandonada"     falta_de_vegetacao = "Falta de vegetação"     lixo_residuos_solidos = "Lixo e resíduos sólidos"     ocupacao_irregular = "Ocupação irregular"     outros = "Outros"     queda_bloco = "Queda de bloco"     recalque = "Recalque"      tipos_opcoes = (         (acesso_irregular, "Acesso irregular"),         (acumulo_sedimentos_pista, "Acumulo de sedimentos sobre a pista"),         (alagamento, "Alagamento"),         (assoreamento, "Assoreamento"),         (atropelamento_animais_silvestres, "Atropelamento de animais             silvestres"),         (deslizamento, "Deslizamento"),         (erosao, "Erosão "),         (estrutura_abandonada, "Estrutura abandonada"),         (falta_de_vegetacao, "Falta de vegetação"),         (lixo_residuos_solidos, "Lixo e resíduos sólidos"),         (ocupacao_irregular, "Ocupação irregular"),         (outros, "Outros"),         (queda_bloco, "Queda de bloco"),         (recalque, "Recalque")     ) nome = models.CharField(max_length=50, choices=tipos_opcoes, blank=True, null=True) causas = models.ManyToManyField(Causa) consequencias = models.ManyToManyField(Consequencia)  def __str__(self):     return self.nome  class Meta:     verbose_name_plural = "Feições"  class Passivo(models.Model): # Opcoes relevo plano = 'PL' ondulado = 'ON' montanhoso = 'MO'  relevo_opcoes = (     (plano, 'Plano'),     (ondulado, 'Ondulado'),     (montanhoso, 'Montanhoso') )  # Opcoes terceira_faixa_localizacao lado_direito = 'LD' lado_esquerdo = 'LE' inexistente = 'IN' ambos = 'AM'  terceira_faixa_localizacao_opcoes = (     (lado_direito, 'Lado Direito'),     (lado_esquerdo, 'Lado Esquerdo'),     (inexistente, 'Inexistente') )  #opcoes pavimento pavimento_asfautico = 'PA' pavimento_concreto = 'PC' nao_pavimentado =  'NP' outro_pavimento = 'OP' pista_rolamento_pavimento_opcoes = (     (pavimento_asfautico, 'Pavimento Asfaltico'),     (pavimento_concreto, 'Pavimento Concreto'),     (nao_pavimentado,  'Nao Pavimentado'),     (outro_pavimento, 'Outro Pavimento') )  # opcoes lado direito = 'D' esquerdo = 'E' indefinido = 'I' ambos = 'A'  lado_opcoes = (     (direito, 'Direito'),     (esquerdo, 'Esquerdo'),     (indefinido, 'Indefinido'),     (ambos, 'Lado Direito e Esquerdo')     )  # Opcoes Perigo sem_perigo = '0' perigo_potencial = '1' perigo_iminente = '2' perigo_instalado = '3'  nivel_gravidade_escolhas = (     (sem_perigo, 'Sem Perigo'),     (perigo_potencial, 'Perigo Potencial'),     (perigo_iminente, 'Perigo Iminente'),     (perigo_instalado, 'Perigo Instalado' ) )  # MODELO data_inspecao = models.DateField('Data de inspeção',auto_now=False)  # LOCALIZAÇÃO latitude = models.DecimalField('Latitude', max_digits=14, decimal_places=10, blank=False, null=True) longitude = models.DecimalField('Longitude', max_digits=14, decimal_places=10, blank=False, null=True) km_ponto = models.DecimalField('Km', blank=True, null=True,max_digits=7, decimal_places=2) lado = models.CharField('Lado de Ocorrência', blank=True, null=True,max_length=1,choices=lado_opcoes) distancia_ao_eixo = models.CharField('Distância do Passivo ao Eixo',max_length=50,blank=True, null=True) area_ocorrencia_faixa_dominio = models.NullBooleanField(blank=True, null=True, default=False) area_ocorrencia_area_adjacente = models.NullBooleanField(blank=True, null=True, default=False)  # CARACTERIZAÇÃO DO SEGMENTO RODOVIÁRIO largura_faixa_dominio_esquerda = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True) largura_faixa_dominio_direita = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True) pista_rolamento_numero = models.IntegerField('nº de pistas de rolamento', blank=True, null=True) pista_rolamento_pavimento =  models.CharField(max_length=50,                 choices = pista_rolamento_pavimento_opcoes,                 default = pavimento_asfautico) acostamento_presenca = models.NullBooleanField('Acostamento', default=False) terceira_faixa_localizacao = models.CharField('Terceira Faixa / Localização', max_length=50,                    choices = terceira_faixa_localizacao_opcoes,                    default = inexistente) relevo = models.CharField(max_length=50,                    choices = relevo_opcoes,                    default = plano)  # CARACTERIZAÇÃO DO PASSIVO # feicao = models.OneToOneField(Feicao, on_delete=models.CASCADE) feicao = models.ForeignKey(Feicao, on_delete=models.DO_NOTHING) dimensao_comprimento = models.DecimalField('Comprimento', max_digits=10, decimal_places=2,blank=True, null=True, default = None) largura_faixa_dominio_total = models.DecimalField('Largura', max_digits=6, decimal_places=2, blank=True, null=True) dimensao_profundidade = models.DecimalField('Profundidade', max_digits=10, decimal_places=2,blank=True, null=True, default = None) risco_ao_usuario = models.CharField(max_length=50, choices = nivel_gravidade_escolhas, default = None,  blank=True, null=True) risco_ao_patrimonio = models.CharField(max_length=50, choices = nivel_gravidade_escolhas, default = None,  blank=True, null=True) risco_ao_ambiente = models.CharField(max_length=50, choices = nivel_gravidade_escolhas, default = None,  blank=True, null=True) possiveis_causas = ChainedManyToManyField(         Causa,         horizontal=True,         verbose_name='Possiveis Causas',         chained_field="feicao",         chained_model_field="feicao",         ) provaveis_consequencias = ChainedManyToManyField(                 Consequencia,                 horizontal=True,                 verbose_name = 'Provaveis Consequências',                 chained_field="feicao",                 chained_model_field="feicao",                 ) localizacao = models.PointField(blank=True, null=True) modelo_3d = models.FileField(upload_to='models/',blank=True, null=True, validators=[FileExtensionValidator(allowed_extensions=['zip'])]) modelo_3d_path =  models.CharField('Endereço do arquivo 3d (cloud.js)',max_length=128,blank=True, null=True) croqui = models.ImageField('Croqui') observacoes = models.TextField() class Meta:     db_table = 'passivo'      class Foto(models.Model): descricao = models.CharField('Descrição',max_length=300, blank=True,     null=True, default = None) image = ImageWithThumbsField(sizes=((100,130),(200,260))) property = models.OneToOneField(Passivo,                                 related_name='fotos',                                 on_delete=models.CASCADE, null=True)#, default='no-img.png')  class Meta:     db_table = 'foto'     verbose_name_plural = "Fotos"      def __str__(self):         return ("Fotos do passivo")    class Local(models.Model): descricao = models.CharField(max_length=55, blank=True, null=True) fk_passivo_passivo = models.OneToOneField(Passivo,on_delete=models.CASCADE)  class Meta:     db_table = 'local' 

Abaixo segue o codigo admin.py from django.contrib import admin from django.apps import apps from cadastramento.models import Feicao, Passivo, Causa, Consequencia, Foto from sorl.thumbnail.admin import AdminImageMixin import nested_admin from leaflet.admin import LeafletGeoAdmin

class FotoInline(AdminImageMixin, admin.TabularInline): model = Foto extra = 0 class PassivoAdmin(AdminImageMixin,nested_admin.NestedModelAdmin): model = Passivo exclude = ['localizacao']   admin.site.register(Causa) admin.site.register(Consequencia) admin.site.register(Feicao) admin.site.register(Passivo,PassivoAdmin) 

Essas opções estavam funcionando, e parou de funcionar. Não me lembro se fiz alguma alteração e que veio a dar esse problema e não consigo encontrar o que deveria ser feito para que funcione.

Simple Chained Flow

I am developing a simple Chained Flow (should I call it by this name?) that uses waterfall as main operation behavior.

Basically we will have a Flow and he will have some dialogs with functions to be executed. So, when you call start on Flow (passing the name of the dialog) some Waterfall objects will be created taking the pointers to the functions pre-stored and executing them. The functions to be executed can call its parent functions to execute some tasks (like calling the next function or reseting to the begin function).

Just take an example in Javascript (easy to understand) code:

var status = false;   var array_of_functions = [     function(parent) {         print("first");          parent.next();     },     function(parent) {         print("second");          if (!status) {             status = true;             // call itself again (not the whole array, reset() should do it)             parent.restart();         }     } ];  doMagic(array_of_functions); 

Output: first -> second -> second;

I’m concerned about the method that I used to make it. Should I try to rewrite in another way or is it good?

Probably the code is a little messy, but I can’t find a better way to solve. And I am using templates to later add some more arguments to the functions that will be called. Taking that, I’m using lambda expressions too to avoid declaring the types in each function (passing a Course object).

The code takes only 2 files, excluding main.

main.cpp

(just a example, I will embed Flow into another Class later)

#include <iostream>  #include "Flow.h"  bool status = false;  void one(Course* course) {     std::cout << "one" << std::endl;     course->doNext(); }  void two(Course* course) {     std::cout << "two" << std::endl;     if (!status) {         status = true;         course->doRestart();     } else {         course->doReplace("another");     } }  void three(Course* course) {     std::cout << "three" << std::endl;     course->doNext(); }  int main() {     std::vector<std::function<void(Course*)>> init = {one, two};     std::vector<std::function<void(Course*)>> another = {three};     Flow<void, Course*> flow;      flow.setDialog("init", steps_x);     flow.setDialog("another", steps_y);      flow.doStart("init");     return 1; } 

Flow.h

#ifndef FLOW_H #define FLOW_H  #include <string> #include <vector> #include <functional>  #include "Waterfall.h"  template <typename rtype, typename ...fargs> class Waterfall; template <typename rtype, typename ...fargs> class Flow {     public:         Flow() {}         ~Flow() {}          struct Node {             std::string name;             std::vector<std::function<rtype(fargs...)>> functions;         };          bool doTrigger(std::string name) {             Node* node;             bool found = false;              for (Node& tmp : _dialogs) {                 if (tmp.name == name) {                     node = &tmp;                     found = true;                     break;                 }             }              if (!found) return false;              Waterfall<rtype, fargs...> waterfall(this, node->functions);             waterfall.doTrigger();             return true;         }          bool setDialog(std::string name, std::vector<std::function<rtype(fargs...)>> functions) {             for (const Node& node : _dialogs) {                 if (node.name == name) {                     return false;                 }             }              Node node = {name, functions};             _dialogs.push_back(node);             return true;         }      private:         std::vector<Node> _dialogs; };  #endif 

Waterfall.h

#ifndef WATERFALL_H #define WATERFALL_H  #include <vector> #include <functional> #include <iostream>  #include "Flow.h"  struct Course {     std::function<void()> doNext;     std::function<void()> doRestart;     std::function<void()> doReset;     std::function<void(std::string)> doReplace; };  template <typename rtype, typename ...fargs> class Flow; template <typename rtype, typename ...fargs> class Waterfall {     public:         Waterfall(Flow<rtype, fargs...>* flow, std::vector<std::function<rtype(fargs...)>>& functions) :             _index(0),             _flow(flow)         {             for (unsigned int i = 0; i < functions.size(); i++) {                 Step step;                 step.callback = &functions[i];                 _steps.push_back(step);             }         }          ~Waterfall() {}          Flow<rtype, fargs...>* getFlow() {return _flow;}          struct Step {             unsigned int count = 0;             std::function<rtype(fargs...)>* callback;         };          bool doTrigger() {             if (_index >= _steps.size()) return false;              Step* step = &_steps[_index];             unsigned int& count = step->count;              Course course;              course.doNext = [this]() {                 this->doNext();             };              course.doRestart = [this]() {                 this->doRestart();             };              course.doReset = [this]() {                 this->doReset();             };              course.doReplace = [this](std::string name) {                 this->getFlow()->doTrigger(name);             };              count++;             (*(step->callback))(&course);             return true;         }          bool doNext() {             if (_index >= _steps.size()) return false;             _index++;             return doTrigger();         }          bool doRestart() {             return doTrigger();         }          bool doReset() {             _index = 0;             return doTrigger();         }      private:         unsigned int _index;         Flow<rtype, fargs...>* _flow;         std::vector<Step> _steps; };  #endif 

You can use this to compile:

#!/bin/bash  g++ -W -Wall -Werror -Wextra -pedantic -O2 \     main.cpp \     Flow.h \     Waterfall.h \ -o main.exe  ./main.exe 

Thanks in advance.

Name for “chained” version upgrades?

Imagine there are two strategies for upgrading something with multiple versions (e.g. an installation of some software).

  1. From any version, upgrade directly to the latest version.

  2. Progressively upgrade your installations, one to the next, until you get to the latest version.

It’s the second of these I’m interested in, and I’m wondering if there is an accepted name for it in our discipline.

Example

As an example, you are on version 7.0, and you want to get to the latest version, 9.1. The upgrade works internally, using the following chained steps.

any -> 8.0 8.0 -> 9.0 9.0 -> current (9.1)