App-vaporcalc

 view release on metacpan or  search on metacpan

README.mkdn  view on Meta::CPAN


## vcalc

    my $calculated = vcalc(
      target_quantity   => 30,   # ml

      base_nic_type     => 'PG', # nicotine base type (VG/PG, default PG)
      base_nic_per_ml   => 100,  # mg/ml (base nicotine concentration)
      target_nic_per_ml => 12,   # mg/ml (target nicotine concentration)

      target_pg         => 65,   # target PG percentage
      target_vg         => 35,   # target VG percentage

      # target flavor(s) name, percentage, base type
      # (or App::vaporcalc::Flavor objects)
      flavor_array => [
        +{ tag => 'Raspberry', percentage => 15, type => 'PG' },
        # ...
      ],
    );

    # Returns an App::vaporcalc::RecipeResultSet ->
    my $recipe = $calculated->recipe;   # App::vaporcalc::Recipe instance
    my $result = $calculated->result;   # App::vaporcalc::Result instance

A functional interface to [App::vaporcalc::RecipeResultSet](https://metacpan.org/pod/App::vaporcalc::RecipeResultSet) -- takes a recipe
(as a list of key/value pairs or an [App::vaporcalc::Recipe](https://metacpan.org/pod/App::vaporcalc::Recipe) object) and

bin/vaporcalc  view on Meta::CPAN

  $lines[0] = colorify red => $lines[0];
  join "\n", @lines
}

fun flavor_strings (RecipeResultSet $rset) {
  my $recipe = $rset->recipe;
  my $result = $rset->result;

  my $flav_recipe_str = '';
  for my $flav ($recipe->flavor_array->all) {
    my $pcnt = colorify 'bold red' => $flav->percentage;
    my $tag  = $flav->tag;
    my $type = $flav->type;
    $flav_recipe_str .= "   $tag -> $pcnt %  ($type)\n";
  }

  my $flav_result_str = '';
  for my $flav ($result->flavors->kv->all) {
    my ($tag, $ml) = @$flav;
    $ml = colorify 'bold yellow' => $ml;
    $flav_result_str .= "   $tag => [$ml ml]\n";

bin/vaporcalc  view on Meta::CPAN

$outfh->say('Welcome to App::vaporcalc!');
$outfh->say("Try '@{[ colorify yellow => 'help' ]}' for usage details.");

my $cmdeng = App::vaporcalc::CmdEngine->new;
my $recipe = App::vaporcalc::Recipe->new(
  target_quantity   => 10,
  base_nic_per_ml   => 100,
  target_nic_per_ml => 12,
  target_pg         => 45,
  target_vg         => 55,
  flavor_percentage => 10,
);
my $initial_input = getopts->recipe ? 'recipe load '.getopts->recipe : undef;

my $orig_prompt = colorify green => 'vcalc> ';
my $prompt;
PROMPT: while (1) {
  $prompt //= $orig_prompt;

  my $input = $initial_input // $term->get_reply(
    prompt  => $prompt,

lib/App/vaporcalc.pm  view on Meta::CPAN


=head2 vcalc

  my $calculated = vcalc(
    target_quantity   => 30,   # ml

    base_nic_type     => 'PG', # nicotine base type (VG/PG, default PG)
    base_nic_per_ml   => 100,  # mg/ml (base nicotine concentration)
    target_nic_per_ml => 12,   # mg/ml (target nicotine concentration)

    target_pg         => 65,   # target PG percentage
    target_vg         => 35,   # target VG percentage

    # target flavor(s) name, percentage, base type
    # (or App::vaporcalc::Flavor objects)
    flavor_array => [
      +{ tag => 'Raspberry', percentage => 15, type => 'PG' },
      # ...
    ],
  );

  # Returns an App::vaporcalc::RecipeResultSet ->
  my $recipe = $calculated->recipe;   # App::vaporcalc::Recipe instance
  my $result = $calculated->result;   # App::vaporcalc::Result instance

A functional interface to L<App::vaporcalc::RecipeResultSet> -- takes a recipe
(as a list of key/value pairs or an L<App::vaporcalc::Recipe> object) and

lib/App/vaporcalc/Cmd/Subject/Flavor.pm  view on Meta::CPAN


method _subject { 'flavor' }
method _build_verb { 'show' }
with 'App::vaporcalc::Role::UI::Cmd';


method _action_show { $self->_action_view }
method _action_view {
  my $output = "Flavors:\n";
  for my $flavor ($self->recipe->flavor_array->all) {
    my $pcnt = $flavor->percentage;
    my $tag  = $flavor->tag;
    my $type = $flavor->type;
    $output .= " $tag -> $pcnt %  ($type)";
  }

  $self->create_result(string => $output)
}

method _action_set {
  my ($tag, $pcnt, $type) = $self->params->all;
  $self->throw_exception(
    message => 'set requires at least a flavor tag and percentage'
  ) unless defined $tag and length $tag and defined $pcnt;

  my $existing = $self->recipe->flavor_array->first_where(
    sub { $_->tag eq $tag }
  );
  my $others = $self->recipe->flavor_array->grep(sub { $_->tag ne $tag });

  $type = $existing->type if $existing and not defined $type;

  my $flavors = [
    $others->all,
    App::vaporcalc::Flavor->new(
            tag        => $tag, 
            percentage => $pcnt, 
      maybe type       => $type,
    )
  ];

  my $recipe = $self->munge_recipe(
    flavor_array => $flavors,
  );
  $self->create_result(recipe => $recipe)
}

method _action_add {
  my ($tag, $pcnt, $type) = $self->params->all;
  $self->throw_exception(
    message => 'add requires at least a flavor tag and percentage'
  ) unless defined $tag and length $tag and defined $pcnt;

  $self->throw_exception(
    message => 'Attempting to add an existing flavor tag'
  ) if $self->recipe->flavor_array->has_any(sub { $_->tag eq $tag });

  my $flavors = array(
    $self->recipe->flavor_array->all,
    App::vaporcalc::Flavor->new(
            tag        => $tag,
            percentage => $pcnt,
      maybe type       => $type,
    )
  );

  my $recipe = $self->munge_recipe(
    flavor_array => $flavors,
  );
  $self->create_result(recipe => $recipe)
}

lib/App/vaporcalc/Flavor.pm  view on Meta::CPAN

package App::vaporcalc::Flavor;
$App::vaporcalc::Flavor::VERSION = '0.005004';
use Defaults::Modern;
use App::vaporcalc::Types -types;

use Moo;

has percentage => (
  required  => 1,
  is        => 'ro',
  isa       => Percentage,
);

has tag => (
  required  => 1,
  is        => 'ro',
  isa       => Str,
);

has type => (
  is        => 'ro',
  isa       => VaporLiquid,
  coerce    => 1,
  builder   => sub { 'PG' },
);

method TO_JSON {
  +{
    percentage => $self->percentage,
    tag        => $self->tag,
    type       => $self->type,
  }
}

with 'App::vaporcalc::Role::Store';

1;

=pod

lib/App/vaporcalc/Flavor.pm  view on Meta::CPAN


  # Usually used via App::vaporcalc::Recipe

=head1 DESCRIPTION

An object representing a flavor extract for use in a
L<App::vaporcalc::Recipe>.

=head2 ATTRIBUTES

=head3 percentage

The total target percentage of this flavor.

=head3 tag

The flavor's identifying tag.

=head3 type

The flavor base (VG/PG).

=head2 CONSUMES

lib/App/vaporcalc/Recipe.pm  view on Meta::CPAN

  isa      => Percentage,
);

has flavor_array      => (
  is      => 'ro',
  isa     => TypedArray[FlavorObject],
  coerce  => 1,
  builder => sub { array_of FlavorObject },
);

method flavor_percentage {
  my $total = 0;
  $total += $_->percentage for $self->flavor_array->all;
  Percentage->assert_return($total)
}

has notes             => (
  lazy    => 1,
  is      => 'ro',
  isa     => TypedArray[Str],
  coerce  => 1,
  builder => sub { array_of Str },
);

lib/App/vaporcalc/Recipe.pm  view on Meta::CPAN

    confess "Expected target_vg + target_pg == 100\n",
      "  target_vg ", $self->target_vg, "\n",
      "  target_pg ", $self->target_pg
  }
}

method BUILDARGS {
  my %params = @_ == 1 ? %{$_[0]} : @_ ? @_ : ();

  # backcompat
  if (my $fpcnt = delete $params{flavor_percentage}) {
    my $fltype = delete $params{flavor_type};
    unless (exists $params{flavor_array}) {
      $params{flavor_array} = [
        +{ 
                tag        => 'Unnamed', 
                percentage => $fpcnt, 
          maybe type       => $fltype
        }
      ];
    }
  }

  \%params
}

method TO_JSON {

lib/App/vaporcalc/Recipe.pm  view on Meta::CPAN


  use App::vaporcalc::Recipe;

  my $recipe = App::vaporcalc::Recipe->new(
    target_quantity   => 30,   # ml

    base_nic_type     => 'PG', # nicotine base type (VG/PG, default PG)
    base_nic_per_ml   => 100,  # mg/ml (base nicotine concentration)
    target_nic_per_ml => 12,   # mg/ml (target nicotine concentration)

    target_pg         => 65,   # target PG percentage
    target_vg         => 35,   # target VG percentage

    flavor_array => [
      +{ tag => 'Raspberry', percentage => 10, type => 'PG' },
      +{ tag => 'EM', percentage => 1, type => 'PG' },
      # ...
    ],

    notes   => [
      'My recipe',
      '10% flavor',
      '1% ethyl maltol'
    ],
  );

lib/App/vaporcalc/Recipe.pm  view on Meta::CPAN

=head3 base_nic_per_ml

The concentration of the base nicotine solution, in mg/ml.

=head3 target_nic_per_ml

The target nicotine concentration, in mg/ml.

=head3 target_pg

The total percentage of PG.

=head3 target_vg

The total percentage of VG.

=head3 flavor_array

A (coercible, see SYNOPSIS) array of L<App::vaporcalc::Flavor> objects.

=head3 notes

A L<List::Objects::WithUtils::Array> containing an arbitrary number of notes
attached to the recipe.

Can be coerced from a plain C<ARRAY>.

=head2 METHODS

=head3 flavor_percentage

Calculates the total flavor percentage; see L</flavor_array>.

=head2 CONSUMES

L<App::vaporcalc::Role::Calc>

L<App::vaporcalc::Role::Store>

=head1 AUTHOR

Jon Portnoy <avenj@cobaltirc.org>

lib/App/vaporcalc/Role/Calc.pm  view on Meta::CPAN

method _calc_total_pg_qty {
  return 0 unless $self->target_pg;
  $self->target_quantity * ($self->target_pg / 100)
}

method _calc_per_flavor_qty_obj {
  my $res = hash_of Object;

  for my $flav (@{ $self->flavor_array }) {
    $flav = FlavorObject->assert_coerce($flav) unless is_FlavorObject $flav;
    my $pcnt = $flav->percentage || next;
    my $ml = $self->target_quantity * ($pcnt / 100);
    $res->set(
      $flav->tag => hash(ml => $ml, type => $flav->type)->inflate
    );
  }

  # hash( $name => $obj );
  #   $obj->ml, $obj->type
  $res
}

lib/App/vaporcalc/Role/Calc.pm  view on Meta::CPAN


=head2 REQUIRES

Consumers need to implement the following methods:

  # Method           Returning
  target_quantity    (ml)
  base_nic_per_ml    (mg/ml)
  base_nic_type      ('PG' or 'VG')
  target_nic_per_ml  (mg/ml)
  target_pg          (percentage)
  target_vg          (percentage)
  flavor_array       (an array of App::vaporcalc::Flavor objects)

=head2 METHODS

=head3 calc

Performs the calculation & returns an L<App::vaporcalc::Result> object.

=head1 AUTHOR

recipes/banana_cheesecake.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Cheesecake Graham Crust",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "INW Banana",
            "percentage" : "0.6"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/banana_cream.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Banana Cream",
            "percentage" : "5"
         },
         {
            "type" : "PG",
            "tag" : "INW Banana",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Bavarian Cream",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "1"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/banana_melon.recipe  view on Meta::CPAN

{
   "recipe" : {
      "target_nic_per_ml" : "3",
      "notes" : [],
      "target_vg" : 60,
      "target_pg" : "40",
      "flavor_array" : [
         {
            "percentage" : "5",
            "type" : "PG",
            "tag" : "TFA Cantelope"
         },
         {
            "type" : "PG",
            "percentage" : "0.5",
            "tag" : "INW Melon"
         },
         {
            "type" : "PG",
            "percentage" : "0.5",
            "tag" : "INW Banana"
         }
      ],
      "base_nic_type" : "PG",
      "target_quantity" : "90",
      "base_nic_per_ml" : 100
   }
}

recipes/banana_peach.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "INW Banana",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "INW Peach",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "TFA Dragonfruit",
            "percentage" : "0.5"
         },
         {
            "type" : "PG",
            "tag" : "TFA Mango",
            "percentage" : "0.5"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "160",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/berries_and_cream.recipe  view on Meta::CPAN

      "target_quantity" : 120.0,
      "target_nic_per_ml" : 3.0,
      "target_vg" : 70,
      "target_pg" : 30,
      "base_nic_type" : "PG",
      "base_nic_per_ml" : 100,
      "notes" : [],
      "flavor_array" : [
         {
            "tag" : "TFA Marshmallow",
            "percentage" : "1",
            "type" : "PG"
         },
         {
            "percentage" : "4",
            "tag" : "TFA Blueberry Wild",
            "type" : "PG"
         },
         {
            "tag" : "INW Strawberry",
            "percentage" : "0.6",
            "type" : "PG"
         },
         {
            "percentage" : "4",
            "tag" : "TFA Bavarian Cream",
            "type" : "PG"
         },
         {
            "type" : "PG",
            "tag" : "TFA Strawberry Ripe",
            "percentage" : "1"
         }
      ]
   }
}

recipes/berrymarshmallow-120ml-3mg.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "TFA Blueberry Extra",
            "percentage" : "3"
         },
         {
            "type" : "PG",
            "tag" : "TFA Vanillin",
            "percentage" : "3"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : [
         "Ended up adding a dash of Sweet Cream and a few drops of Circus Cotton Candy"

recipes/birthdaycake.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Vanilla Cupcake",
            "percentage" : "4"
         },
         {
            "type" : "PG",
            "tag" : "TFA Frosted Donut",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Vanilla Swirl",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA VBIC",
            "percentage" : "0.5"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/blubreeze.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Blueberry Wild",
            "percentage" : "6"
         },
         {
            "type" : "PG",
            "tag" : "Menthol (10%)",
            "percentage" : "1"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "200",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/blurazz.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "INW Peach",
            "percentage" : "0.5"
         },
         {
            "type" : "PG",
            "tag" : "INW Raspberry",
            "percentage" : "1.5"
         },
         {
            "type" : "PG",
            "tag" : "TFA Dragonfruit",
            "percentage" : "0.5"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "160",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/cantaloupe.recipe  view on Meta::CPAN

      "target_quantity" : "90",
      "base_nic_type" : "PG",
      "base_nic_per_ml" : 100,
      "target_vg" : 60,
      "target_nic_per_ml" : "3",
      "notes" : [],
      "flavor_array" : [
         {
            "tag" : "TFA Cantelope",
            "type" : "PG",
            "percentage" : "5"
         },
         {
            "tag" : "INW Melon",
            "percentage" : "0.3",
            "type" : "PG"
         }
      ],
      "target_pg" : "40"
   }
}

recipes/captain.recipe  view on Meta::CPAN

{
   "recipe" : {
      "base_nic_type" : "PG",
      "flavor_array" : [
         {
            "type" : "PG",
            "percentage" : "2",
            "tag" : "TFA Bavarian Cream"
         },
         {
            "percentage" : "2",
            "tag" : "TFA Strawberry Ripe",
            "type" : "PG"
         },
         {
            "type" : "PG",
            "tag" : "TFA Berry Crunch",
            "percentage" : "4"
         },
         {
            "type" : "PG",
            "percentage" : "2",
            "tag" : "TFA Blueberry Wild"
         },
         {
            "type" : "PG",
            "percentage" : "0.5",
            "tag" : "TFA Sweet Cream"
         }
      ],
      "target_nic_per_ml" : 3,
      "notes" : [],
      "base_nic_per_ml" : 100,
      "target_vg" : 70,
      "target_quantity" : 120,
      "target_pg" : 30
   }

recipes/caramel_cream.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Caramel",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Caramel Candy",
            "percentage" : "3"
         },
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Sweet Cream",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Vanilla Cupcake",
            "percentage" : "1"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/cherrycheesecake.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Cheesecake Graham Crust",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "INW Cherries",
            "percentage" : "2"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/cherrylime-50ml-3mg.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Strawberry (Ripe)",
            "percentage" : "3"
         },
         {
            "type" : "PG",
            "tag" : "TFA Key Lime",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Double Kiwi",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "TFA Energy Drink",
            "percentage" : "2"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "55",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : [
         "Kind of a cherry-lime taste.",

recipes/cherrylime_batch_2.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Key Lime",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Double Kiwi",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "TFA Dragonfruit",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "INW Cherries",
            "percentage" : "2"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "55",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/cherryvanilla.recipe  view on Meta::CPAN

{
   "recipe" : {
      "target_nic_per_ml" : 3,
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA VBIC",
            "percentage" : "3"
         },
         {
            "type" : "PG",
            "percentage" : "2",
            "tag" : "Vanillin (10%)"
         },
         {
            "tag" : "INW Cherries",
            "percentage" : "0.8",
            "type" : "PG"
         },
         {
            "tag" : "TFA Vanilla Swirl",
            "percentage" : "4",
            "type" : "PG"
         }
      ],
      "base_nic_type" : "PG",
      "target_pg" : 30,
      "target_quantity" : 120,
      "base_nic_per_ml" : 100,
      "target_vg" : 70,
      "notes" : []
   }

recipes/chocmint-100ml-3mg.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Double Chocolate",
            "percentage" : "8"
         },
         {
            "type" : "PG",
            "tag" : "E.M.",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Peppermint",
            "percentage" : "0.5"
         }
      ],
      "target_pg" : 45,
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "100",
      "target_nic_per_ml" : "3",
      "target_vg" : 55,
      "notes" : []
   }

recipes/creamymelon.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "INW Melon",
            "percentage" : "2"
         },
         {
            "type" : "PG",
            "tag" : "TFA Bavarian Cream",
            "percentage" : "3"
         },
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "1"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/creamymint-120ml-3mg.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Creme de Menthe",
            "percentage" : "4"
         },
         {
            "type" : "PG",
            "tag" : "TFA Marshmallow",
            "percentage" : "3"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/double_kiwi.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Double Kiwi",
            "percentage" : "4"
         },
         {
            "type" : "PG",
            "tag" : "TFA Dragonfruit",
            "percentage" : "3"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "125",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/grape_candy-50ml-6mg.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Grape Candy",
            "percentage" : "6.15"
         },
         {
            "type" : "PG",
            "tag" : "TFA Grape Juice",
            "percentage" : "6.15"
         }
      ],
      "target_pg" : "40",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "50",
      "target_nic_per_ml" : "6",
      "target_vg" : 60,
      "notes" : []
   }

recipes/kiwi-mint_120ml-3mg.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Peppermint",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Double Kiwi",
            "percentage" : "7"
         },
         {
            "type" : "PG",
            "tag" : "TFA Dragonfruit",
            "percentage" : "3"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "120",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }

recipes/kiwi_cherry.recipe  view on Meta::CPAN

{
   "recipe" : {
      "flavor_array" : [
         {
            "type" : "PG",
            "tag" : "TFA Double Kiwi",
            "percentage" : "3"
         },
         {
            "type" : "PG",
            "tag" : "INW Cherries",
            "percentage" : "1"
         },
         {
            "type" : "PG",
            "tag" : "TFA Dragonfruit",
            "percentage" : "0.5"
         }
      ],
      "target_pg" : "30",
      "base_nic_per_ml" : 100,
      "base_nic_type" : "PG",
      "target_quantity" : "160",
      "target_nic_per_ml" : "3",
      "target_vg" : 70,
      "notes" : []
   }



( run in 0.482 second using v1.01-cache-2.11-cpan-05162d3a2b1 )