# The main frame, the parent of all.

package Slic3r::GUI::MainFrame;
use strict;
use warnings;
use utf8;

use File::Basename qw(basename dirname);
use List::Util qw(min);
use Slic3r::Geometry qw(X Y Z);
use Wx qw(:frame :bitmap :id :misc :panel :sizer :menu :dialog :filedialog
    :font :icon :notebook wxTheApp);
use Wx::Event qw(EVT_CLOSE EVT_NOTEBOOK_PAGE_CHANGED);
use base 'Wx::Frame';

our $qs_last_input_file;
our $qs_last_output_file;
our $last_config;

sub new {
    my ($class) = @_;

    my $self = $class->SUPER::new(undef, -1, 'Slic3r', wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE);
    if ($^O eq 'MSWin32') {
        $self->SetIcon(Wx::Icon->new($Slic3r::var->("Slic3r.ico"), wxBITMAP_TYPE_ICO));
    } else {
        $self->SetIcon(Wx::Icon->new($Slic3r::var->("Slic3r_128px.png"), wxBITMAP_TYPE_PNG));
    }

    $self->{loaded} = 0;
    $self->{preset_editor_tabs} = {};  # group => panel

    # initialize tabpanel and menubar
    $self->_init_tabpanel;
    $self->_init_menubar;

    # set default tooltip timer in msec
    # SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values
    # (SetAutoPop is not available on GTK.)
    eval { Wx::ToolTip::SetAutoPop(32767) };

    # initialize status bar
    $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, -1);
    $self->{statusbar}->SetStatusText("Version $Slic3r::VERSION - Remember to check for updates at http://slic3r.org/");
    $self->SetStatusBar($self->{statusbar});

    $self->{loaded} = 1;

    # initialize layout
    {
        my $sizer = Wx::BoxSizer->new(wxVERTICAL);
        $sizer->Add($self->{tabpanel}, 1, wxEXPAND);
        $sizer->SetSizeHints($self);
        $self->SetSizer($sizer);
        $self->Fit;
        $self->SetMinSize([760, 490]);
        $self->SetSize($self->GetMinSize);
        wxTheApp->restore_window_pos($self, "main_frame");
        $self->Show;
        $self->Layout;
    }

    # declare events
    EVT_CLOSE($self, sub {
        my (undef, $event) = @_;

        if ($event->CanVeto) {
            if (!$self->{plater}->prompt_unsaved_changes) {
                $event->Veto;
                return;
            }

            if ($self->{controller} && $self->{controller}->printing) {
                my $confirm = Wx::MessageDialog->new($self, "You are currently printing. Do you want to stop printing and continue anyway?",
                    'Unfinished Print', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
                if ($confirm->ShowModal == wxID_NO) {
                    $event->Veto;
                    return;
                }
            }
        }

        # save window size
        wxTheApp->save_window_pos($self, "main_frame");

        # propagate event
        $event->Skip;
    });

    return $self;
}

sub _init_tabpanel {
    my ($self) = @_;

    $self->{tabpanel} = my $panel = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
    EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub {
        my $panel = $self->{tabpanel}->GetCurrentPage;
        $panel->OnActivate if $panel->can('OnActivate');
    });

    $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater");
    $panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), "Controller")
        if ($Slic3r::GUI::Settings->{_}{show_host});

    if ($Slic3r::GUI::Settings->{_}{tabbed_preset_editors}) {
        foreach my $group (qw(print filament printer)) {
            $self->{plater}->show_preset_editor($group, 0, $panel);
        }
    }

}

sub _init_menubar {
    my ($self) = @_;

    # File menu
    my $fileMenu = Wx::Menu->new;
    {
        wxTheApp->append_menu_item($fileMenu, "Open STL/OBJ/AMF/3MF…\tCtrl+O", 'Open a model', sub {
            $self->{plater}->add if $self->{plater};
        }, undef, 'brick_add.png');
        wxTheApp->append_menu_item($fileMenu, "Open 2.5D TIN mesh…", 'Import a 2.5D TIN mesh', sub {
            $self->{plater}->add_tin if $self->{plater};
        }, undef, 'map_add.png');
        $fileMenu->AppendSeparator();
        wxTheApp->append_menu_item($fileMenu, "&Load Config…\tCtrl+L", 'Load exported configuration file', sub {
            $self->load_config_file;
        }, undef, 'plugin_add.png');
        wxTheApp->append_menu_item($fileMenu, "&Export Config…\tCtrl+E", 'Export current configuration to file', sub {
            $self->export_config;
        }, undef, 'plugin_go.png');
        wxTheApp->append_menu_item($fileMenu, "&Load Config Bundle…", 'Load presets from a bundle', sub {
            $self->load_configbundle;
        }, undef, 'lorry_add.png');
        wxTheApp->append_menu_item($fileMenu, "&Export Config Bundle…", 'Export all presets to file', sub {
            $self->export_configbundle;
        }, undef, 'lorry_go.png');
        wxTheApp->append_menu_item($fileMenu, "&Import Config from GCode-File…", 'Load presets from a created GCode-File', sub {
            $self->import_fromGCode;
        }, undef, 'lorry_import.png');
        $fileMenu->AppendSeparator();
        my $repeat;
        wxTheApp->append_menu_item($fileMenu, "Q&uick Slice…\tCtrl+U", 'Slice file', sub {
            wxTheApp->CallAfter(sub {
                $self->quick_slice;
                $repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
            });
        }, undef, 'cog_go.png');
        wxTheApp->append_menu_item($fileMenu, "Quick Slice and Save &As…\tCtrl+Alt+U", 'Slice file and save as', sub {
            wxTheApp->CallAfter(sub {
                $self->quick_slice(save_as => 1);
                $repeat->Enable(defined $Slic3r::GUI::MainFrame::last_input_file);
            });
        }, undef, 'cog_go.png');
        $repeat = wxTheApp->append_menu_item($fileMenu, "&Repeat Last Quick Slice\tCtrl+Shift+U", 'Repeat last quick slice', sub {
            wxTheApp->CallAfter(sub {
                $self->quick_slice(reslice => 1);
            });
        }, undef, 'cog_go.png');
        $repeat->Enable(0);
        $fileMenu->AppendSeparator();
        wxTheApp->append_menu_item($fileMenu, "Slice to SV&G…\tCtrl+G", 'Slice file to SVG', sub {
            $self->quick_slice(save_as => 1, export_svg => 1);
        }, undef, 'shape_handles.png');
        $fileMenu->AppendSeparator();
        wxTheApp->append_menu_item($fileMenu, "Repair STL file…", 'Automatically repair an STL file', sub {
            $self->repair_stl;
        }, undef, 'wrench.png');
        $fileMenu->AppendSeparator();
        # Cmd+, is standard on OS X - what about other operating systems?
        wxTheApp->append_menu_item($fileMenu, "Preferences…\tCtrl+,", 'Application preferences', sub {
            Slic3r::GUI::Preferences->new($self)->ShowModal;
        }, wxID_PREFERENCES);
        $fileMenu->AppendSeparator();
        wxTheApp->append_menu_item($fileMenu, "&Quit", 'Quit Slic3r', sub {
            $self->Close(0);
        }, wxID_EXIT);
    }

    # Plater menu
    {
        my $plater = $self->{plater};

        $self->{plater_menu} = Wx::Menu->new;
        {
            my $selectMenu = $self->{plater_select_menu} = Wx::Menu->new;
            wxTheApp->append_submenu($self->{plater_menu}, "Select", 'Select an object in the plater', $selectMenu, undef, 'brick.png');
        }
        wxTheApp->append_menu_item($self->{plater_menu}, "Undo\tCtrl+Z", 'Undo', sub {
                $plater->undo;
            }, undef, 'arrow_undo.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Redo\tCtrl+Shift+Z", 'Redo', sub {
                $plater->redo;
            }, undef, 'arrow_redo.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Select Next Object\tCtrl+Right", 'Select Next Object in the plater', sub {
            $plater->select_next;
        }, undef, 'arrow_right.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Select Prev Object\tCtrl+Left", 'Select Previous Object in the plater', sub {
            $plater->select_prev;
        }, undef, 'arrow_left.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Zoom In\tCtrl+up", 'Zoom In',
            sub { $self->{plater}->zoom('in') }, undef, 'zoom_in.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Zoom Out\tCtrl+down", 'Zoom Out',
            sub { $self->{plater}->zoom('out') }, undef, 'zoom_out.png');
        $self->{plater_menu}->AppendSeparator();
        wxTheApp->append_menu_item($self->{plater_menu}, "Export G-code...", 'Export current plate as G-code', sub {
            $plater->export_gcode;
        }, undef, 'cog_go.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Export plate as STL...", 'Export current plate as STL', sub {
            $plater->export_stl;
        }, undef, 'brick_go.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Export plate with modifiers as AMF...", 'Export current plate as AMF, including all modifier meshes', sub {
            $plater->export_amf;
        }, undef, 'brick_go.png');
        wxTheApp->append_menu_item($self->{plater_menu}, "Export plate with modifiers as 3MF...", 'Export current plate as 3MF, including all modifier meshes', sub {
                $plater->export_tmf;
            }, undef, 'brick_go.png');
        $self->{object_menu} = $self->{plater}->object_menu;
        $self->on_plater_object_list_changed(0);
        $self->on_plater_selection_changed(0);
    }

    # Settings menu
    my $settingsMenu = Wx::Menu->new;
    {
        wxTheApp->append_menu_item($settingsMenu, "P&rint Settings…\tCtrl+1", 'Show the print settings editor', sub {
            $self->{plater}->show_preset_editor('print');
        }, undef, 'cog.png');
        wxTheApp->append_menu_item($settingsMenu, "&Filament Settings…\tCtrl+2", 'Show the filament settings editor', sub {
            $self->{plater}->show_preset_editor('filament');
        }, undef, 'spool.png');
        wxTheApp->append_menu_item($settingsMenu, "Print&er Settings…\tCtrl+3", 'Show the printer settings editor', sub {
            $self->{plater}->show_preset_editor('printer');
        }, undef, 'printer_empty.png');
    }

    # View menu
    {
        $self->{viewMenu} = Wx::Menu->new;
        wxTheApp->append_menu_item($self->{viewMenu}, "Top\tCtrl+4"     , 'Top View'     , sub { $self->select_view('top'     ); });
        wxTheApp->append_menu_item($self->{viewMenu}, "Bottom\tCtrl+5"  , 'Bottom View'  , sub { $self->select_view('bottom'  ); });
        wxTheApp->append_menu_item($self->{viewMenu}, "Left\tCtrl+6"    , 'Left View'    , sub { $self->select_view('left'    ); });
        wxTheApp->append_menu_item($self->{viewMenu}, "Right\tCtrl+7"   , 'Right View'   , sub { $self->select_view('right'   ); });
        wxTheApp->append_menu_item($self->{viewMenu}, "Front\tCtrl+8"   , 'Front View'   , sub { $self->select_view('front'   ); });
        wxTheApp->append_menu_item($self->{viewMenu}, "Back\tCtrl+9"    , 'Back View'    , sub { $self->select_view('back'    ); });
        wxTheApp->append_menu_item($self->{viewMenu}, "Diagonal\tCtrl+0", 'Diagonal View', sub { $self->select_view('diagonal'); });
        $self->{viewMenu}->AppendSeparator();
        $self->{color_toolpaths_by_role} = wxTheApp->append_menu_item($self->{viewMenu},
            "Color Toolpaths by Role",
            'Color toolpaths according to perimeter/infill/support material',
            sub {
                $Slic3r::GUI::Settings->{_}{color_toolpaths_by} = 'role';
                wxTheApp->save_settings;
                $self->{plater}{preview3D}->reload_print;
            },
            undef, undef, wxITEM_RADIO
        );
        $self->{color_toolpaths_by_extruder} = wxTheApp->append_menu_item($self->{viewMenu},
            "Color Toolpaths by Filament",
            'Color toolpaths using the configured extruder/filament color',
            sub {
                $Slic3r::GUI::Settings->{_}{color_toolpaths_by} = 'extruder';
                wxTheApp->save_settings;
                $self->{plater}{preview3D}->reload_print;
            },
            undef, undef, wxITEM_RADIO
        );
        if ($Slic3r::GUI::Settings->{_}{color_toolpaths_by} eq 'role') {
            $self->{color_toolpaths_by_role}->Check(1);
        } else {
            $self->{color_toolpaths_by_extruder}->Check(1);
        }
    }

    # Window menu
    my $windowMenu = Wx::Menu->new;
    {
        wxTheApp->append_menu_item($windowMenu, "&Plater\tCtrl+T", 'Show the plater', sub {
            $self->select_tab(0);
        }, undef, 'application_view_tile.png');
        wxTheApp->append_menu_item($windowMenu, "&Controller\tCtrl+Y", 'Show the printer controller', sub {
            if ($Slic3r::GUI::Settings->{_}{show_host}) {
                $self->select_tab(1);
            } else {
                my $confirm = Wx::MessageDialog->new($self, "The printer controller is currently disabled in the preferences. Do you want to enable it?",
                    'Controller', wxICON_QUESTION | wxYES_NO | wxYES_DEFAULT);
                if ($confirm->ShowModal == wxID_YES) {
                    $Slic3r::GUI::Settings->{_}{show_host} = 1;
                    wxTheApp->save_settings;
                    Slic3r::GUI::show_info($self, "The controller is now enabled. You must restart Slic3r now to make the change effective.", "Controller");
                }
            }
        }, undef, 'printer_empty.png');
        wxTheApp->append_menu_item($windowMenu, "DLP Projector…\tCtrl+P", 'Open projector window for DLP printing', sub {
            $self->{plater}->pause_background_process;
            $self->{slaconfig} = Slic3r::Config->new;
            Slic3r::GUI::SLAPrintOptions->new($self)->ShowModal;
            $self->{plater}->resume_background_process;
        }, undef, 'film.png');
    }

    # Help menu
    my $helpMenu = Wx::Menu->new;
    {
        wxTheApp->append_menu_item($helpMenu, "&Configuration $Slic3r::GUI::ConfigWizard::wizard…", "Run Configuration $Slic3r::GUI::ConfigWizard::wizard", sub {
            $self->config_wizard;
        });
        $helpMenu->AppendSeparator();
        wxTheApp->append_menu_item($helpMenu, "Slic3r &Website", 'Open the Slic3r website in your browser', sub {
            Wx::LaunchDefaultBrowser('http://slic3r.org/');
        });
        my $versioncheck = wxTheApp->append_menu_item($helpMenu, "Check for &Updates...", 'Check for new Slic3r versions', sub {
            wxTheApp->check_version(1);
        });
        $versioncheck->Enable(wxTheApp->have_version_check);
        wxTheApp->append_menu_item($helpMenu, "Slic3r &Manual", 'Open the Slic3r manual in your browser', sub {
            Wx::LaunchDefaultBrowser('http://manual.slic3r.org/');
        });
        $helpMenu->AppendSeparator();
        wxTheApp->append_menu_item($helpMenu, "&About Slic3r", 'Show about dialog', sub {
            wxTheApp->about;
        });
    }

    # menubar
    # assign menubar to frame after appending items, otherwise special items
    # will not be handled correctly
    {
        my $menubar = Wx::MenuBar->new;
        $menubar->Append($fileMenu, "&File");
        $menubar->Append($self->{plater_menu}, "&Plater") if $self->{plater_menu};
        $menubar->Append($self->{object_menu}, "&Object") if $self->{object_menu};
        $menubar->Append($settingsMenu, "&Settings");
        $menubar->Append($self->{viewMenu}, "&View") if $self->{viewMenu};
        $menubar->Append($windowMenu, "&Window");
        $menubar->Append($helpMenu, "&Help");
        $self->SetMenuBar($menubar);
    }
}

sub is_loaded {
    my ($self) = @_;
    return $self->{loaded};
}

sub on_undo_redo_stacks_changed {
    my $self = shift;
    # Enable undo or redo if they have operations in their stack.
    $self->{plater_menu}->Enable($self->{plater_menu}->FindItem("Undo\tCtrl+Z"), $#{$self->{plater}->{undo_stack}} < 0 ? 0 : 1);
    $self->{plater_menu}->Enable( $self->{plater_menu}->FindItem("Redo\tCtrl+Shift+Z"),  $#{$self->{plater}->{redo_stack}} < 0 ? 0 : 1);
}

sub on_plater_object_list_changed {
    my ($self, $have_objects) = @_;

    return if !defined $self->{plater_menu};
    $self->{plater_menu}->Enable($_->GetId, $have_objects)
        for $self->{plater_menu}->GetMenuItems;
    $self->on_undo_redo_stacks_changed;
}

sub on_plater_selection_changed {
    my ($self, $have_selection) = @_;

    return if !defined $self->{object_menu};
    $self->{object_menu}->Enable($_->GetId, $have_selection)
        for $self->{object_menu}->GetMenuItems;
    $self->on_undo_redo_stacks_changed;

}

sub quick_slice {
    my $self = shift;
    my %params = @_;

    my $progress_dialog;
    eval {
        # validate configuration
        my $config = $self->{plater}->config;
        $config->validate;

        # select input file
        my $input_file;
        my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
        if (!$params{reslice}) {
            my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/3MF):', $dir, "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
            if ($dialog->ShowModal != wxID_OK) {
                $dialog->Destroy;
                return;
            }
            $input_file = Slic3r::decode_path($dialog->GetPaths);
            $dialog->Destroy;
            $qs_last_input_file = $input_file unless $params{export_svg};
        } else {
            if (!defined $qs_last_input_file) {
                Wx::MessageDialog->new($self, "No previously sliced file.",
                                       'Error', wxICON_ERROR | wxOK)->ShowModal();
                return;
            }
            if (! -e $qs_last_input_file) {
                Wx::MessageDialog->new($self, "Previously sliced file ($qs_last_input_file) not found.",
                                       'File Not Found', wxICON_ERROR | wxOK)->ShowModal();
                return;
            }
            $input_file = $qs_last_input_file;
        }
        my $input_file_basename = basename($input_file);
        $Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file);
        wxTheApp->save_settings;

        my $print_center;
        {
            my $bed_shape = Slic3r::Polygon->new_scale(@{$config->bed_shape});
            $print_center = Slic3r::Pointf->new_unscale(@{$bed_shape->bounding_box->center});
        }

        my $sprint = Slic3r::Print::Simple->new(
            print_center    => $print_center,
            status_cb       => sub {
                my ($percent, $message) = @_;
                return if &Wx::wxVERSION_STRING !~ / 2\.(8\.|9\.[2-9])/;
                $progress_dialog->Update($percent, "$message…");
            },
        );

        # keep model around
        my $model = Slic3r::Model->read_from_file($input_file);

        $sprint->apply_config($config);
        $sprint->set_model($model);
        # FIXME: populate placeholders (preset names etc.)

        # select output file
        my $output_file;
        if ($params{reslice}) {
            $output_file = $qs_last_output_file if defined $qs_last_output_file;
        } elsif ($params{save_as}) {
            $output_file = $sprint->output_filepath;
            $output_file =~ s/\.gcode$/.svg/i if $params{export_svg};
            my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:',
                wxTheApp->output_path(dirname($output_file)),
                basename($output_file), $params{export_svg} ? &Slic3r::GUI::FILE_WILDCARDS->{svg} : &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
            if ($dlg->ShowModal != wxID_OK) {
                $dlg->Destroy;
                return;
            }
            $output_file = Slic3r::decode_path($dlg->GetPath);
            $qs_last_output_file = $output_file unless $params{export_svg};
            $Slic3r::GUI::Settings->{_}{last_output_path} = dirname($output_file);
            wxTheApp->save_settings;
            $dlg->Destroy;
        }

        # show processbar dialog
        $progress_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…",
            100, $self, 0);
        $progress_dialog->Pulse;

        {
            my @warnings = ();
            local $SIG{__WARN__} = sub { push @warnings, $_[0] };

            $sprint->output_file($output_file);
            if ($params{export_svg}) {
                $sprint->export_svg;
            } else {
                $sprint->export_gcode;
            }
            $sprint->status_cb(undef);
            Slic3r::GUI::warning_catcher($self)->($_) for @warnings;
        }
        $progress_dialog->Destroy;
        undef $progress_dialog;

        my $message = "$input_file_basename was successfully sliced.";
        wxTheApp->notify($message);
        Wx::MessageDialog->new($self, $message, 'Slicing Done!',
            wxOK | wxICON_INFORMATION)->ShowModal;
    };
    Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog });
}

sub repair_stl {
    my $self = shift;

    my $input_file;
    {
        my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
        my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:', $dir, "", &Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
        if ($dialog->ShowModal != wxID_OK) {
            $dialog->Destroy;
            return;
        }
        $input_file = Slic3r::decode_path($dialog->GetPaths);
        $dialog->Destroy;
    }

    my $output_file = $input_file;
    {
        $output_file =~ s/\.stl$/_fixed.obj/i;
        my $dlg = Wx::FileDialog->new($self, "Save OBJ file (less prone to coordinate errors than STL) as:", dirname($output_file),
            basename($output_file), &Slic3r::GUI::FILE_WILDCARDS->{obj}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
        if ($dlg->ShowModal != wxID_OK) {
            $dlg->Destroy;
            return undef;
        }
        $output_file = Slic3r::decode_path($dlg->GetPath);
        $dlg->Destroy;
    }

    my $tmesh = Slic3r::TriangleMesh->new;
    $tmesh->ReadSTLFile($input_file);
    $tmesh->repair;
    $tmesh->WriteOBJFile($output_file);
    Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair");
}

sub export_config {
    my $self = shift;

    my $config = $self->{plater}->config;
    eval {
        # validate configuration
        $config->validate;
    };
    Slic3r::GUI::catch_error($self) and return;

    my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
    my $filename = $last_config ? basename($last_config) : "config.ini";
    my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename,
        &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
    if ($dlg->ShowModal == wxID_OK) {
        my $file = Slic3r::decode_path($dlg->GetPath);
        $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
        wxTheApp->save_settings;
        $last_config = $file;
        $config->save($file);
    }
    $dlg->Destroy;
}

sub load_config_file {
    my $self = shift;
    my ($file) = @_;

    if (!$file) {
        my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
        my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
                &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
        return unless $dlg->ShowModal == wxID_OK;
        $file = Slic3r::decode_path($dlg->GetPaths);
        $dlg->Destroy;
    }
    $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
    wxTheApp->save_settings;
    $last_config = $file;

    my $name = wxTheApp->add_external_preset($file);
    $self->{plater}->load_presets;
    $self->{plater}->select_preset_by_name($name, $_) for qw(print filament printer);
}

sub import_fromGCode{ # import configuration from gcode file sliced with Slic3r
    my ($self, $file) = @_;

    if (!$file) {
        my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
        my $dlg = Wx::FileDialog->new($self, 'Select GCode File to load config from:', $dir, &Slic3r::GUI::FILE_WILDCARDS->{gcode}, &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
        return unless $dlg->ShowModal == wxID_OK;
        $file = Slic3r::decode_path($dlg->GetPaths);
        $dlg->Destroy;
    }

    $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
    wxTheApp->save_settings;

    # open $file and read the first line to make sure it was sliced using Slic3r
    open(FILEFIRSTLINE, '<', "$file")
        or die( "Can't open file to import gcode: $!" );
    my $firstLine = <FILEFIRSTLINE>;
    close (FILEFIRSTLINE);

    # Exit, if file was not sliced using Slic3r
    if( index($firstLine, "generated by Slic3r") < 0){
        return;
    }

    # if file sliced by Slic3r, read it
    open(GFILE, "$file")
        or die( "Can't open file to import gcode: $!" );
    my @lines = reverse <GFILE>; # read the file from the back

    my $line;
    my @settinglines="";
    foreach $line (@lines) {
        # if line is empty, we're done -> EOF
        if (substr($line, 0, 1) eq ";"){
            $line = substr($line,2, length($line)-2);
            push @settinglines, $line;
        } else {
            last;
        }
    }

    close (GFILE);

    # (over-) write config to temp-file -> <gcode-filename.ini>
    my $tempfile = substr $file, 0, rindex( $file, q{.} );
    $tempfile="$tempfile.ini";

    open (TEMPFILESETTINGS, "> $tempfile");
    print TEMPFILESETTINGS @settinglines;
    close (TEMPFILESETTINGS);

    $self->load_config_file($tempfile);

    # todo: do we want to delete the <gcode-filename.ini> file after load_config?

}

sub export_configbundle {
    my $self = shift;

    eval {
        # validate current configuration in case it's dirty
        $self->{plater}->config->validate;
    };
    Slic3r::GUI::catch_error($self) and return;

    my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
    my $filename = "Slic3r_config_bundle.ini";
    my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', $dir, $filename,
        &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
    if ($dlg->ShowModal == wxID_OK) {
        my $file = Slic3r::decode_path($dlg->GetPath);
        $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
        wxTheApp->save_settings;

        # leave default category empty to prevent the bundle from being parsed as a normal config file
        my $ini = { _ => {} };
        $ini->{settings}{$_} = $Slic3r::GUI::Settings->{_}{$_} for qw(autocenter);
        $ini->{presets} = $Slic3r::GUI::Settings->{presets};

        foreach my $section (qw(print filament printer)) {
            my @presets = @{wxTheApp->presets->{$section}};
            foreach my $preset (@presets) {
                next if $preset->default || $preset->external;
                $ini->{"$section:" . $preset->name} = $preset->load_config->as_ini->{_};
            }
        }

        Slic3r::Config->write_ini($file, $ini);
    }
    $dlg->Destroy;
}

sub load_configbundle {
    my ($self, $file, $skip_no_id) = @_;

    if (!$file) {
        my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
        my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
                &Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
        return unless $dlg->ShowModal == wxID_OK;
        $file = Slic3r::decode_path($dlg->GetPaths);
        $dlg->Destroy;
    }

    $Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
    wxTheApp->save_settings;

    # load .ini file
    my $ini = Slic3r::Config->read_ini($file);

    if ($ini->{settings}) {
        $Slic3r::GUI::Settings->{_}{$_} = $ini->{settings}{$_} for keys %{$ini->{settings}};
        wxTheApp->save_settings;
    }
    if ($ini->{presets}) {
        $Slic3r::GUI::Settings->{presets} = $ini->{presets};
        wxTheApp->save_settings;
    }
    my $imported = 0;
    INI_BLOCK: foreach my $ini_category (sort keys %$ini) {
        next unless $ini_category =~ /^(print|filament|printer):(.+)$/;
        my ($section, $preset_name) = ($1, $2);
        my $config = Slic3r::Config->load_ini_hash($ini->{$ini_category});
        next if $skip_no_id && !$config->get($section . "_settings_id");

        {
            my @current_presets = @{wxTheApp->presets->{$section}};
            my %current_ids = map { $_ => 1 }
                grep $_,
                map $_->dirty_config->get($section . "_settings_id"),
                @current_presets;
            next INI_BLOCK if exists $current_ids{$config->get($section . "_settings_id")};
        }

        $config->save(sprintf "$Slic3r::GUI::datadir/%s/%s.ini", $section, $preset_name);
        Slic3r::debugf "Imported %s preset %s\n", $section, $preset_name;
        $imported++;
    }
    $self->{plater}->load_presets;

    return if !$imported;

    my $message = sprintf "%d presets successfully imported.", $imported;
    Slic3r::GUI::show_info($self, $message);
}

sub load_config {
    my ($self, $config) = @_;

    $self->{plater}->load_config($config);
}

sub config_wizard {
    my $self = shift;

    if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) {
        foreach my $group (qw(print filament printer)) {
            my $name = 'My Settings';
            $config->save(sprintf "$Slic3r::GUI::datadir/%s/%s.ini", $group, $name);
            $Slic3r::GUI::Settings->{presets}{$group} = "$name.ini";
            $self->{plater}->load_presets;
            $self->{plater}->select_preset_by_name($name, $group);
        }
    }
}

sub select_tab {
    my ($self, $tab) = @_;
    $self->{tabpanel}->SetSelection($tab);
}

# Set a camera direction, zoom to all objects.
sub select_view {
    my ($self, $direction) = @_;

    $self->{plater}->select_view($direction);
}

1;


Output: redis


OC.L10N.register(
    "dicomviewer",
    {
    "Reset" : "重設",
    "OK" : "確定",
    "Close" : "關閉",
    "Download" : "下載",
    "More" : "更多"
},
"nplurals=1; plural=0;");


# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
#     I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
#     <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
#     I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# To learn more, please read the Rails Internationalization guide
# available at http://guides.rubyonrails.org/i18n.html.

en:
  hello: "Hello world"


# Tests for the binary collations.

--echo #
--echo # Bug#30350111: UTF8MB4_0900_BIN STRINGS CANNOT BE COMPARED WITH
--echo #               UTF8MB4_0900_AI_CI STRINGS
--echo #

CREATE TABLE t(id INT PRIMARY KEY AUTO_INCREMENT,
               col_aici VARCHAR(10) COLLATE utf8mb4_0900_ai_ci,
               col_bin VARCHAR(10) COLLATE utf8mb4_bin,
               col_0900_bin VARCHAR(10) COLLATE utf8mb4_0900_bin);
INSERT INTO t(col_aici)
VALUES ('abc'), ('ABC'), ('Abc'), ('abc '), ('ABC  '), ('Abc   ');
UPDATE t SET col_bin = col_aici, col_0900_bin = col_aici;

# Binary collation wins over non-binary collation. Comparison should
# be done using the utf8mb4_bin collation (PAD SPACE).
SELECT CONCAT('''', t1.col_aici, ''' = ''', t2.col_aici, '''')
  FROM t t1, t t2
  WHERE t1.col_aici = t2.col_bin
  ORDER BY t1.id, t2.id;

# Binary collation wins over non-binary collation. Comparison should
# be done using the utf8mb4_0900_bin collation (NO PAD).
SELECT CONCAT('''', t1.col_aici, ''' = ''', t2.col_aici, '''')
  FROM t t1, t t2
  WHERE t1.col_aici = t2.col_0900_bin
  ORDER BY t1.id, t2.id;

# Two different binary collations. Don't know which to choose.
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT CONCAT('''', t1.col_aici, ''' = ''', t2.col_aici, '''')
  FROM t t1, t t2
  WHERE t1.col_bin = t2.col_0900_bin
  ORDER BY t1.id, t2.id;
--error ER_CANT_AGGREGATE_2COLLATIONS
SELECT CONCAT('''', t1.col_aici, ''' = ''', t2.col_aici, '''')
  FROM t t1, t t2
  WHERE t1.col_0900_bin = t2.col_bin
  ORDER BY t1.id, t2.id;

# Binary collation wins over non-binary collation. The UNION uses the
# utf8mb4_bin collation (PAD SPACE).
--sorted_result
SELECT col_aici FROM t UNION SELECT col_bin FROM t;

# Binary collation wins over non-binary collation. The UNION uses the
# utf8mb4_0900_bin collation (NO PAD).
--sorted_result
SELECT col_aici FROM t UNION SELECT col_0900_bin FROM t;

# Cannot decide whether to use PAD SPACE or NO_PAD.
--error ER_CANT_AGGREGATE_NCOLLATIONS
SELECT col_bin FROM t UNION SELECT col_0900_bin FROM t;
--error ER_CANT_AGGREGATE_NCOLLATIONS
SELECT col_0900_bin FROM t UNION SELECT col_bin FROM t;
--error ER_CANT_AGGREGATE_NCOLLATIONS
SELECT col_bin FROM t UNION SELECT col_0900_bin FROM t
  UNION SELECT col_aici FROM t;

# Add an explicit collation into the mix. The explicit collation is used.
--sorted_result
SELECT col_bin FROM t UNION SELECT col_0900_bin FROM t
  UNION SELECT col_aici COLLATE utf8mb4_0900_ai_ci FROM t;
--sorted_result
SELECT col_bin FROM t UNION SELECT col_0900_bin FROM t
  UNION SELECT col_aici COLLATE utf8mb4_bin FROM t;
--sorted_result
SELECT col_bin FROM t UNION SELECT col_0900_bin FROM t
  UNION SELECT col_aici COLLATE utf8mb4_0900_bin FROM t;

DROP TABLE t;

# Verify that the deprecated BINARY type attribute uses utf8mb4_bin as
# the binary collation of utf8mb4.
CREATE TABLE t(x VARCHAR(10) BINARY);
SELECT COLLATION(MAX(x)) FROM t;
DROP TABLE t;


/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * Date: 28 May 2001
 *
 * SUMMARY:  Functions are scoped statically, not dynamically
 *
 * See ECMA Section 10.1.4 Scope Chain and Identifier Resolution
 * (This section defines the scope chain of an execution context)
 *
 * See ECMA Section 12.10 The with Statement
 *
 * See ECMA Section 13 Function Definition
 * (This section defines the scope chain of a function object as that
 *  of the running execution context when the function was declared)
 *
 * Like scope-001.js, but using assignment var f = function expression
 * instead of a function declaration: function f() {} etc.
 */
//-----------------------------------------------------------------------------
var gTestfile = 'scope-002.js';
var UBound = 0;
var BUGNUMBER = '(none)';
var summary = 'Testing that functions are scoped statically, not dynamically';
var self = this;  // capture a reference to the global object
var status = '';
var statusitems = [ ];
var actual = '';
var actualvalues = [ ];
var expect= '';
var expectedvalues = [ ];

/*
 * In this section the expected value is 1, not 2.
 *
 * Why? f captures its scope chain from when it's declared, and imposes that chain
 * when it's executed. In other words, f's scope chain is from when it was compiled.
 * Since f is a top-level function, this is the global object only. Hence 'a' resolves to 1.
 */
status = 'Section A of test';
var a = 1;
var f = function () {return a;};
var obj = {a:2};
with (obj)
{
  actual = f();
}
expect = 1;
addThis();

/*
 * In this section the expected value is 2, not 1. That is because here
 * f's associated scope chain now includes 'obj' before the global object.
 */
status = 'Section B of test';
var a = 1;
var obj = {a:2};
with (obj)
{
  var f = function () {return a;};
  actual = f();
}
expect = 2;
addThis();

/*
 * Like Section B , except that we call f outside the with block.
 * By the principles explained above, we still expect 2 -
 */
status = 'Section C of test';
var a = 1;
var obj = {a:2};
with (obj)
{
  var f = function () {return a;};
}
actual = f();
expect = 2;
addThis();

/*
 * Like Section C, but with one more level of indirection -
 */
status = 'Section D of test';
var a = 1;
var obj = {a:2, obj:{a:3}};
with (obj)
{
  with (obj)
  {
    var f = function () {return a;};
  }
}
actual = f();
expect = 3;
addThis();

/*
 * Like Section C, but here we actually delete obj before calling f.
 * We still expect 2 -
 */
status = 'Section E of test';
var a = 1;
var obj = {a:2};
with (obj)
{
  var f = function () {return a;};
}
delete obj;
actual = f();
expect = 2;
addThis();

/*
 * Like Section E. Here we redefine obj and call f under with (obj) -
 * We still expect 2 -
 */
status = 'Section F of test';
var a = 1;
var obj = {a:2};
with (obj)
{
  var f = function () {return a;};
}
delete obj;
var obj = {a:3};
with (obj)
{
  actual = f();
}
expect = 2;  // NOT 3 !!!
addThis();

/*
 * Explicitly verify that f exists at global level, even though
 * it was defined under the with(obj) block -
 */
status = 'Section G of test';
var a = 1;
var obj = {a:2};
with (obj)
{
  var f = function () {return a;};
}
actual = String([obj.hasOwnProperty('f'), self.hasOwnProperty('f')]);
expect = String([false, true]);
addThis();

/*
 * Explicitly verify that f exists at global level, even though
 * it was defined under the with(obj) block -
 */
status = 'Section H of test';
var a = 1;
var obj = {a:2};
with (obj)
{
  var f = function () {return a;};
}
actual = String(['f' in obj, 'f' in self]);
expect = String([false, true]);
addThis();

//-------------------------------------------------------------------------------------------------
test();
//-------------------------------------------------------------------------------------------------

function addThis()
{
  statusitems[UBound] = status;
  actualvalues[UBound] = actual;
  expectedvalues[UBound] = expect;
  UBound++;
  resetTestVars();
}

function resetTestVars()
{
  delete a;
  delete obj;
  delete f;
}

function test()
{
  enterFunc ('test');
  printBugNumber(BUGNUMBER);
  printStatus (summary);

  for (var i = 0; i < UBound; i++)
  {
    reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
  }

  exitFunc ('test');
}


/*
 * debug.h - NTFS kernel debug support. Part of the Linux-NTFS project.
 *
 * Copyright (c) 2001-2004 Anton Altaparmakov
 *
 * This program/include file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program/include file is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (in the main directory of the Linux-NTFS
 * distribution in the file COPYING); if not, write to the Free Software
 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _LINUX_NTFS_DEBUG_H
#define _LINUX_NTFS_DEBUG_H

#include <linux/fs.h>

#include "runlist.h"

#ifdef DEBUG

extern int debug_msgs;

extern __printf(4, 5)
void __ntfs_debug(const char *file, int line, const char *function,
		  const char *format, ...);
/**
 * ntfs_debug - write a debug level message to syslog
 * @f:		a printf format string containing the message
 * @...:	the variables to substitute into @f
 *
 * ntfs_debug() writes a DEBUG level message to the syslog but only if the
 * driver was compiled with -DDEBUG. Otherwise, the call turns into a NOP.
 */
#define ntfs_debug(f, a...)						\
	__ntfs_debug(__FILE__, __LINE__, __func__, f, ##a)

extern void ntfs_debug_dump_runlist(const runlist_element *rl);

#else	/* !DEBUG */

#define ntfs_debug(fmt, ...)						\
do {									\
	if (0)								\
		no_printk(fmt, ##__VA_ARGS__);				\
} while (0)

#define ntfs_debug_dump_runlist(rl)	do {} while (0)

#endif	/* !DEBUG */

extern  __printf(3, 4)
void __ntfs_warning(const char *function, const struct super_block *sb,
		    const char *fmt, ...);
#define ntfs_warning(sb, f, a...)	__ntfs_warning(__func__, sb, f, ##a)

extern  __printf(3, 4)
void __ntfs_error(const char *function, const struct super_block *sb,
		  const char *fmt, ...);
#define ntfs_error(sb, f, a...)		__ntfs_error(__func__, sb, f, ##a)

#endif /* _LINUX_NTFS_DEBUG_H */


// Variables
// --------------------------

@fa-font-path:        "../fonts";
@fa-font-size-base:   14px;
@fa-line-height-base: 1;
//@fa-font-path:        "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly
@fa-css-prefix:       fa;
@fa-version:          "4.7.0";
@fa-border-color:     #eee;
@fa-inverse:          #fff;
@fa-li-width:         (30em / 14);

@fa-var-500px: "\f26e";
@fa-var-address-book: "\f2b9";
@fa-var-address-book-o: "\f2ba";
@fa-var-address-card: "\f2bb";
@fa-var-address-card-o: "\f2bc";
@fa-var-adjust: "\f042";
@fa-var-adn: "\f170";
@fa-var-align-center: "\f037";
@fa-var-align-justify: "\f039";
@fa-var-align-left: "\f036";
@fa-var-align-right: "\f038";
@fa-var-amazon: "\f270";
@fa-var-ambulance: "\f0f9";
@fa-var-american-sign-language-interpreting: "\f2a3";
@fa-var-anchor: "\f13d";
@fa-var-android: "\f17b";
@fa-var-angellist: "\f209";
@fa-var-angle-double-down: "\f103";
@fa-var-angle-double-left: "\f100";
@fa-var-angle-double-right: "\f101";
@fa-var-angle-double-up: "\f102";
@fa-var-angle-down: "\f107";
@fa-var-angle-left: "\f104";
@fa-var-angle-right: "\f105";
@fa-var-angle-up: "\f106";
@fa-var-apple: "\f179";
@fa-var-archive: "\f187";
@fa-var-area-chart: "\f1fe";
@fa-var-arrow-circle-down: "\f0ab";
@fa-var-arrow-circle-left: "\f0a8";
@fa-var-arrow-circle-o-down: "\f01a";
@fa-var-arrow-circle-o-left: "\f190";
@fa-var-arrow-circle-o-right: "\f18e";
@fa-var-arrow-circle-o-up: "\f01b";
@fa-var-arrow-circle-right: "\f0a9";
@fa-var-arrow-circle-up: "\f0aa";
@fa-var-arrow-down: "\f063";
@fa-var-arrow-left: "\f060";
@fa-var-arrow-right: "\f061";
@fa-var-arrow-up: "\f062";
@fa-var-arrows: "\f047";
@fa-var-arrows-alt: "\f0b2";
@fa-var-arrows-h: "\f07e";
@fa-var-arrows-v: "\f07d";
@fa-var-asl-interpreting: "\f2a3";
@fa-var-assistive-listening-systems: "\f2a2";
@fa-var-asterisk: "\f069";
@fa-var-at: "\f1fa";
@fa-var-audio-description: "\f29e";
@fa-var-automobile: "\f1b9";
@fa-var-backward: "\f04a";
@fa-var-balance-scale: "\f24e";
@fa-var-ban: "\f05e";
@fa-var-bandcamp: "\f2d5";
@fa-var-bank: "\f19c";
@fa-var-bar-chart: "\f080";
@fa-var-bar-chart-o: "\f080";
@fa-var-barcode: "\f02a";
@fa-var-bars: "\f0c9";
@fa-var-bath: "\f2cd";
@fa-var-bathtub: "\f2cd";
@fa-var-battery: "\f240";
@fa-var-battery-0: "\f244";
@fa-var-battery-1: "\f243";
@fa-var-battery-2: "\f242";
@fa-var-battery-3: "\f241";
@fa-var-battery-4: "\f240";
@fa-var-battery-empty: "\f244";
@fa-var-battery-full: "\f240";
@fa-var-battery-half: "\f242";
@fa-var-battery-quarter: "\f243";
@fa-var-battery-three-quarters: "\f241";
@fa-var-bed: "\f236";
@fa-var-beer: "\f0fc";
@fa-var-behance: "\f1b4";
@fa-var-behance-square: "\f1b5";
@fa-var-bell: "\f0f3";
@fa-var-bell-o: "\f0a2";
@fa-var-bell-slash: "\f1f6";
@fa-var-bell-slash-o: "\f1f7";
@fa-var-bicycle: "\f206";
@fa-var-binoculars: "\f1e5";
@fa-var-birthday-cake: "\f1fd";
@fa-var-bitbucket: "\f171";
@fa-var-bitbucket-square: "\f172";
@fa-var-bitcoin: "\f15a";
@fa-var-black-tie: "\f27e";
@fa-var-blind: "\f29d";
@fa-var-bluetooth: "\f293";
@fa-var-bluetooth-b: "\f294";
@fa-var-bold: "\f032";
@fa-var-bolt: "\f0e7";
@fa-var-bomb: "\f1e2";
@fa-var-book: "\f02d";
@fa-var-bookmark: "\f02e";
@fa-var-bookmark-o: "\f097";
@fa-var-braille: "\f2a1";
@fa-var-briefcase: "\f0b1";
@fa-var-btc: "\f15a";
@fa-var-bug: "\f188";
@fa-var-building: "\f1ad";
@fa-var-building-o: "\f0f7";
@fa-var-bullhorn: "\f0a1";
@fa-var-bullseye: "\f140";
@fa-var-bus: "\f207";
@fa-var-buysellads: "\f20d";
@fa-var-cab: "\f1ba";
@fa-var-calculator: "\f1ec";
@fa-var-calendar: "\f073";
@fa-var-calendar-check-o: "\f274";
@fa-var-calendar-minus-o: "\f272";
@fa-var-calendar-o: "\f133";
@fa-var-calendar-plus-o: "\f271";
@fa-var-calendar-times-o: "\f273";
@fa-var-camera: "\f030";
@fa-var-camera-retro: "\f083";
@fa-var-car: "\f1b9";
@fa-var-caret-down: "\f0d7";
@fa-var-caret-left: "\f0d9";
@fa-var-caret-right: "\f0da";
@fa-var-caret-square-o-down: "\f150";
@fa-var-caret-square-o-left: "\f191";
@fa-var-caret-square-o-right: "\f152";
@fa-var-caret-square-o-up: "\f151";
@fa-var-caret-up: "\f0d8";
@fa-var-cart-arrow-down: "\f218";
@fa-var-cart-plus: "\f217";
@fa-var-cc: "\f20a";
@fa-var-cc-amex: "\f1f3";
@fa-var-cc-diners-club: "\f24c";
@fa-var-cc-discover: "\f1f2";
@fa-var-cc-jcb: "\f24b";
@fa-var-cc-mastercard: "\f1f1";
@fa-var-cc-paypal: "\f1f4";
@fa-var-cc-stripe: "\f1f5";
@fa-var-cc-visa: "\f1f0";
@fa-var-certificate: "\f0a3";
@fa-var-chain: "\f0c1";
@fa-var-chain-broken: "\f127";
@fa-var-check: "\f00c";
@fa-var-check-circle: "\f058";
@fa-var-check-circle-o: "\f05d";
@fa-var-check-square: "\f14a";
@fa-var-check-square-o: "\f046";
@fa-var-chevron-circle-down: "\f13a";
@fa-var-chevron-circle-left: "\f137";
@fa-var-chevron-circle-right: "\f138";
@fa-var-chevron-circle-up: "\f139";
@fa-var-chevron-down: "\f078";
@fa-var-chevron-left: "\f053";
@fa-var-chevron-right: "\f054";
@fa-var-chevron-up: "\f077";
@fa-var-child: "\f1ae";
@fa-var-chrome: "\f268";
@fa-var-circle: "\f111";
@fa-var-circle-o: "\f10c";
@fa-var-circle-o-notch: "\f1ce";
@fa-var-circle-thin: "\f1db";
@fa-var-clipboard: "\f0ea";
@fa-var-clock-o: "\f017";
@fa-var-clone: "\f24d";
@fa-var-close: "\f00d";
@fa-var-cloud: "\f0c2";
@fa-var-cloud-download: "\f0ed";
@fa-var-cloud-upload: "\f0ee";
@fa-var-cny: "\f157";
@fa-var-code: "\f121";
@fa-var-code-fork: "\f126";
@fa-var-codepen: "\f1cb";
@fa-var-codiepie: "\f284";
@fa-var-coffee: "\f0f4";
@fa-var-cog: "\f013";
@fa-var-cogs: "\f085";
@fa-var-columns: "\f0db";
@fa-var-comment: "\f075";
@fa-var-comment-o: "\f0e5";
@fa-var-commenting: "\f27a";
@fa-var-commenting-o: "\f27b";
@fa-var-comments: "\f086";
@fa-var-comments-o: "\f0e6";
@fa-var-compass: "\f14e";
@fa-var-compress: "\f066";
@fa-var-connectdevelop: "\f20e";
@fa-var-contao: "\f26d";
@fa-var-copy: "\f0c5";
@fa-var-copyright: "\f1f9";
@fa-var-creative-commons: "\f25e";
@fa-var-credit-card: "\f09d";
@fa-var-credit-card-alt: "\f283";
@fa-var-crop: "\f125";
@fa-var-crosshairs: "\f05b";
@fa-var-css3: "\f13c";
@fa-var-cube: "\f1b2";
@fa-var-cubes: "\f1b3";
@fa-var-cut: "\f0c4";
@fa-var-cutlery: "\f0f5";
@fa-var-dashboard: "\f0e4";
@fa-var-dashcube: "\f210";
@fa-var-database: "\f1c0";
@fa-var-deaf: "\f2a4";
@fa-var-deafness: "\f2a4";
@fa-var-dedent: "\f03b";
@fa-var-delicious: "\f1a5";
@fa-var-desktop: "\f108";
@fa-var-deviantart: "\f1bd";
@fa-var-diamond: "\f219";
@fa-var-digg: "\f1a6";
@fa-var-dollar: "\f155";
@fa-var-dot-circle-o: "\f192";
@fa-var-download: "\f019";
@fa-var-dribbble: "\f17d";
@fa-var-drivers-license: "\f2c2";
@fa-var-drivers-license-o: "\f2c3";
@fa-var-dropbox: "\f16b";
@fa-var-drupal: "\f1a9";
@fa-var-edge: "\f282";
@fa-var-edit: "\f044";
@fa-var-eercast: "\f2da";
@fa-var-eject: "\f052";
@fa-var-ellipsis-h: "\f141";
@fa-var-ellipsis-v: "\f142";
@fa-var-empire: "\f1d1";
@fa-var-envelope: "\f0e0";
@fa-var-envelope-o: "\f003";
@fa-var-envelope-open: "\f2b6";
@fa-var-envelope-open-o: "\f2b7";
@fa-var-envelope-square: "\f199";
@fa-var-envira: "\f299";
@fa-var-eraser: "\f12d";
@fa-var-etsy: "\f2d7";
@fa-var-eur: "\f153";
@fa-var-euro: "\f153";
@fa-var-exchange: "\f0ec";
@fa-var-exclamation: "\f12a";
@fa-var-exclamation-circle: "\f06a";
@fa-var-exclamation-triangle: "\f071";
@fa-var-expand: "\f065";
@fa-var-expeditedssl: "\f23e";
@fa-var-external-link: "\f08e";
@fa-var-external-link-square: "\f14c";
@fa-var-eye: "\f06e";
@fa-var-eye-slash: "\f070";
@fa-var-eyedropper: "\f1fb";
@fa-var-fa: "\f2b4";
@fa-var-facebook: "\f09a";
@fa-var-facebook-f: "\f09a";
@fa-var-facebook-official: "\f230";
@fa-var-facebook-square: "\f082";
@fa-var-fast-backward: "\f049";
@fa-var-fast-forward: "\f050";
@fa-var-fax: "\f1ac";
@fa-var-feed: "\f09e";
@fa-var-female: "\f182";
@fa-var-fighter-jet: "\f0fb";
@fa-var-file: "\f15b";
@fa-var-file-archive-o: "\f1c6";
@fa-var-file-audio-o: "\f1c7";
@fa-var-file-code-o: "\f1c9";
@fa-var-file-excel-o: "\f1c3";
@fa-var-file-image-o: "\f1c5";
@fa-var-file-movie-o: "\f1c8";
@fa-var-file-o: "\f016";
@fa-var-file-pdf-o: "\f1c1";
@fa-var-file-photo-o: "\f1c5";
@fa-var-file-picture-o: "\f1c5";
@fa-var-file-powerpoint-o: "\f1c4";
@fa-var-file-sound-o: "\f1c7";
@fa-var-file-text: "\f15c";
@fa-var-file-text-o: "\f0f6";
@fa-var-file-video-o: "\f1c8";
@fa-var-file-word-o: "\f1c2";
@fa-var-file-zip-o: "\f1c6";
@fa-var-files-o: "\f0c5";
@fa-var-film: "\f008";
@fa-var-filter: "\f0b0";
@fa-var-fire: "\f06d";
@fa-var-fire-extinguisher: "\f134";
@fa-var-firefox: "\f269";
@fa-var-first-order: "\f2b0";
@fa-var-flag: "\f024";
@fa-var-flag-checkered: "\f11e";
@fa-var-flag-o: "\f11d";
@fa-var-flash: "\f0e7";
@fa-var-flask: "\f0c3";
@fa-var-flickr: "\f16e";
@fa-var-floppy-o: "\f0c7";
@fa-var-folder: "\f07b";
@fa-var-folder-o: "\f114";
@fa-var-folder-open: "\f07c";
@fa-var-folder-open-o: "\f115";
@fa-var-font: "\f031";
@fa-var-font-awesome: "\f2b4";
@fa-var-fonticons: "\f280";
@fa-var-fort-awesome: "\f286";
@fa-var-forumbee: "\f211";
@fa-var-forward: "\f04e";
@fa-var-foursquare: "\f180";
@fa-var-free-code-camp: "\f2c5";
@fa-var-frown-o: "\f119";
@fa-var-futbol-o: "\f1e3";
@fa-var-gamepad: "\f11b";
@fa-var-gavel: "\f0e3";
@fa-var-gbp: "\f154";
@fa-var-ge: "\f1d1";
@fa-var-gear: "\f013";
@fa-var-gears: "\f085";
@fa-var-genderless: "\f22d";
@fa-var-get-pocket: "\f265";
@fa-var-gg: "\f260";
@fa-var-gg-circle: "\f261";
@fa-var-gift: "\f06b";
@fa-var-git: "\f1d3";
@fa-var-git-square: "\f1d2";
@fa-var-github: "\f09b";
@fa-var-github-alt: "\f113";
@fa-var-github-square: "\f092";
@fa-var-gitlab: "\f296";
@fa-var-gittip: "\f184";
@fa-var-glass: "\f000";
@fa-var-glide: "\f2a5";
@fa-var-glide-g: "\f2a6";
@fa-var-globe: "\f0ac";
@fa-var-google: "\f1a0";
@fa-var-google-plus: "\f0d5";
@fa-var-google-plus-circle: "\f2b3";
@fa-var-google-plus-official: "\f2b3";
@fa-var-google-plus-square: "\f0d4";
@fa-var-google-wallet: "\f1ee";
@fa-var-graduation-cap: "\f19d";
@fa-var-gratipay: "\f184";
@fa-var-grav: "\f2d6";
@fa-var-group: "\f0c0";
@fa-var-h-square: "\f0fd";
@fa-var-hacker-news: "\f1d4";
@fa-var-hand-grab-o: "\f255";
@fa-var-hand-lizard-o: "\f258";
@fa-var-hand-o-down: "\f0a7";
@fa-var-hand-o-left: "\f0a5";
@fa-var-hand-o-right: "\f0a4";
@fa-var-hand-o-up: "\f0a6";
@fa-var-hand-paper-o: "\f256";
@fa-var-hand-peace-o: "\f25b";
@fa-var-hand-pointer-o: "\f25a";
@fa-var-hand-rock-o: "\f255";
@fa-var-hand-scissors-o: "\f257";
@fa-var-hand-spock-o: "\f259";
@fa-var-hand-stop-o: "\f256";
@fa-var-handshake-o: "\f2b5";
@fa-var-hard-of-hearing: "\f2a4";
@fa-var-hashtag: "\f292";
@fa-var-hdd-o: "\f0a0";
@fa-var-header: "\f1dc";
@fa-var-headphones: "\f025";
@fa-var-heart: "\f004";
@fa-var-heart-o: "\f08a";
@fa-var-heartbeat: "\f21e";
@fa-var-history: "\f1da";
@fa-var-home: "\f015";
@fa-var-hospital-o: "\f0f8";
@fa-var-hotel: "\f236";
@fa-var-hourglass: "\f254";
@fa-var-hourglass-1: "\f251";
@fa-var-hourglass-2: "\f252";
@fa-var-hourglass-3: "\f253";
@fa-var-hourglass-end: "\f253";
@fa-var-hourglass-half: "\f252";
@fa-var-hourglass-o: "\f250";
@fa-var-hourglass-start: "\f251";
@fa-var-houzz: "\f27c";
@fa-var-html5: "\f13b";
@fa-var-i-cursor: "\f246";
@fa-var-id-badge: "\f2c1";
@fa-var-id-card: "\f2c2";
@fa-var-id-card-o: "\f2c3";
@fa-var-ils: "\f20b";
@fa-var-image: "\f03e";
@fa-var-imdb: "\f2d8";
@fa-var-inbox: "\f01c";
@fa-var-indent: "\f03c";
@fa-var-industry: "\f275";
@fa-var-info: "\f129";
@fa-var-info-circle: "\f05a";
@fa-var-inr: "\f156";
@fa-var-instagram: "\f16d";
@fa-var-institution: "\f19c";
@fa-var-internet-explorer: "\f26b";
@fa-var-intersex: "\f224";
@fa-var-ioxhost: "\f208";
@fa-var-italic: "\f033";
@fa-var-joomla: "\f1aa";
@fa-var-jpy: "\f157";
@fa-var-jsfiddle: "\f1cc";
@fa-var-key: "\f084";
@fa-var-keyboard-o: "\f11c";
@fa-var-krw: "\f159";
@fa-var-language: "\f1ab";
@fa-var-laptop: "\f109";
@fa-var-lastfm: "\f202";
@fa-var-lastfm-square: "\f203";
@fa-var-leaf: "\f06c";
@fa-var-leanpub: "\f212";
@fa-var-legal: "\f0e3";
@fa-var-lemon-o: "\f094";
@fa-var-level-down: "\f149";
@fa-var-level-up: "\f148";
@fa-var-life-bouy: "\f1cd";
@fa-var-life-buoy: "\f1cd";
@fa-var-life-ring: "\f1cd";
@fa-var-life-saver: "\f1cd";
@fa-var-lightbulb-o: "\f0eb";
@fa-var-line-chart: "\f201";
@fa-var-link: "\f0c1";
@fa-var-linkedin: "\f0e1";
@fa-var-linkedin-square: "\f08c";
@fa-var-linode: "\f2b8";
@fa-var-linux: "\f17c";
@fa-var-list: "\f03a";
@fa-var-list-alt: "\f022";
@fa-var-list-ol: "\f0cb";
@fa-var-list-ul: "\f0ca";
@fa-var-location-arrow: "\f124";
@fa-var-lock: "\f023";
@fa-var-long-arrow-down: "\f175";
@fa-var-long-arrow-left: "\f177";
@fa-var-long-arrow-right: "\f178";
@fa-var-long-arrow-up: "\f176";
@fa-var-low-vision: "\f2a8";
@fa-var-magic: "\f0d0";
@fa-var-magnet: "\f076";
@fa-var-mail-forward: "\f064";
@fa-var-mail-reply: "\f112";
@fa-var-mail-reply-all: "\f122";
@fa-var-male: "\f183";
@fa-var-map: "\f279";
@fa-var-map-marker: "\f041";
@fa-var-map-o: "\f278";
@fa-var-map-pin: "\f276";
@fa-var-map-signs: "\f277";
@fa-var-mars: "\f222";
@fa-var-mars-double: "\f227";
@fa-var-mars-stroke: "\f229";
@fa-var-mars-stroke-h: "\f22b";
@fa-var-mars-stroke-v: "\f22a";
@fa-var-maxcdn: "\f136";
@fa-var-meanpath: "\f20c";
@fa-var-medium: "\f23a";
@fa-var-medkit: "\f0fa";
@fa-var-meetup: "\f2e0";
@fa-var-meh-o: "\f11a";
@fa-var-mercury: "\f223";
@fa-var-microchip: "\f2db";
@fa-var-microphone: "\f130";
@fa-var-microphone-slash: "\f131";
@fa-var-minus: "\f068";
@fa-var-minus-circle: "\f056";
@fa-var-minus-square: "\f146";
@fa-var-minus-square-o: "\f147";
@fa-var-mixcloud: "\f289";
@fa-var-mobile: "\f10b";
@fa-var-mobile-phone: "\f10b";
@fa-var-modx: "\f285";
@fa-var-money: "\f0d6";
@fa-var-moon-o: "\f186";
@fa-var-mortar-board: "\f19d";
@fa-var-motorcycle: "\f21c";
@fa-var-mouse-pointer: "\f245";
@fa-var-music: "\f001";
@fa-var-navicon: "\f0c9";
@fa-var-neuter: "\f22c";
@fa-var-newspaper-o: "\f1ea";
@fa-var-object-group: "\f247";
@fa-var-object-ungroup: "\f248";
@fa-var-odnoklassniki: "\f263";
@fa-var-odnoklassniki-square: "\f264";
@fa-var-opencart: "\f23d";
@fa-var-openid: "\f19b";
@fa-var-opera: "\f26a";
@fa-var-optin-monster: "\f23c";
@fa-var-outdent: "\f03b";
@fa-var-pagelines: "\f18c";
@fa-var-paint-brush: "\f1fc";
@fa-var-paper-plane: "\f1d8";
@fa-var-paper-plane-o: "\f1d9";
@fa-var-paperclip: "\f0c6";
@fa-var-paragraph: "\f1dd";
@fa-var-paste: "\f0ea";
@fa-var-pause: "\f04c";
@fa-var-pause-circle: "\f28b";
@fa-var-pause-circle-o: "\f28c";
@fa-var-paw: "\f1b0";
@fa-var-paypal: "\f1ed";
@fa-var-pencil: "\f040";
@fa-var-pencil-square: "\f14b";
@fa-var-pencil-square-o: "\f044";
@fa-var-percent: "\f295";
@fa-var-phone: "\f095";
@fa-var-phone-square: "\f098";
@fa-var-photo: "\f03e";
@fa-var-picture-o: "\f03e";
@fa-var-pie-chart: "\f200";
@fa-var-pied-piper: "\f2ae";
@fa-var-pied-piper-alt: "\f1a8";
@fa-var-pied-piper-pp: "\f1a7";
@fa-var-pinterest: "\f0d2";
@fa-var-pinterest-p: "\f231";
@fa-var-pinterest-square: "\f0d3";
@fa-var-plane: "\f072";
@fa-var-play: "\f04b";
@fa-var-play-circle: "\f144";
@fa-var-play-circle-o: "\f01d";
@fa-var-plug: "\f1e6";
@fa-var-plus: "\f067";
@fa-var-plus-circle: "\f055";
@fa-var-plus-square: "\f0fe";
@fa-var-plus-square-o: "\f196";
@fa-var-podcast: "\f2ce";
@fa-var-power-off: "\f011";
@fa-var-print: "\f02f";
@fa-var-product-hunt: "\f288";
@fa-var-puzzle-piece: "\f12e";
@fa-var-qq: "\f1d6";
@fa-var-qrcode: "\f029";
@fa-var-question: "\f128";
@fa-var-question-circle: "\f059";
@fa-var-question-circle-o: "\f29c";
@fa-var-quora: "\f2c4";
@fa-var-quote-left: "\f10d";
@fa-var-quote-right: "\f10e";
@fa-var-ra: "\f1d0";
@fa-var-random: "\f074";
@fa-var-ravelry: "\f2d9";
@fa-var-rebel: "\f1d0";
@fa-var-recycle: "\f1b8";
@fa-var-reddit: "\f1a1";
@fa-var-reddit-alien: "\f281";
@fa-var-reddit-square: "\f1a2";
@fa-var-refresh: "\f021";
@fa-var-registered: "\f25d";
@fa-var-remove: "\f00d";
@fa-var-renren: "\f18b";
@fa-var-reorder: "\f0c9";
@fa-var-repeat: "\f01e";
@fa-var-reply: "\f112";
@fa-var-reply-all: "\f122";
@fa-var-resistance: "\f1d0";
@fa-var-retweet: "\f079";
@fa-var-rmb: "\f157";
@fa-var-road: "\f018";
@fa-var-rocket: "\f135";
@fa-var-rotate-left: "\f0e2";
@fa-var-rotate-right: "\f01e";
@fa-var-rouble: "\f158";
@fa-var-rss: "\f09e";
@fa-var-rss-square: "\f143";
@fa-var-rub: "\f158";
@fa-var-ruble: "\f158";
@fa-var-rupee: "\f156";
@fa-var-s15: "\f2cd";
@fa-var-safari: "\f267";
@fa-var-save: "\f0c7";
@fa-var-scissors: "\f0c4";
@fa-var-scribd: "\f28a";
@fa-var-search: "\f002";
@fa-var-search-minus: "\f010";
@fa-var-search-plus: "\f00e";
@fa-var-sellsy: "\f213";
@fa-var-send: "\f1d8";
@fa-var-send-o: "\f1d9";
@fa-var-server: "\f233";
@fa-var-share: "\f064";
@fa-var-share-alt: "\f1e0";
@fa-var-share-alt-square: "\f1e1";
@fa-var-share-square: "\f14d";
@fa-var-share-square-o: "\f045";
@fa-var-shekel: "\f20b";
@fa-var-sheqel: "\f20b";
@fa-var-shield: "\f132";
@fa-var-ship: "\f21a";
@fa-var-shirtsinbulk: "\f214";
@fa-var-shopping-bag: "\f290";
@fa-var-shopping-basket: "\f291";
@fa-var-shopping-cart: "\f07a";
@fa-var-shower: "\f2cc";
@fa-var-sign-in: "\f090";
@fa-var-sign-language: "\f2a7";
@fa-var-sign-out: "\f08b";
@fa-var-signal: "\f012";
@fa-var-signing: "\f2a7";
@fa-var-simplybuilt: "\f215";
@fa-var-sitemap: "\f0e8";
@fa-var-skyatlas: "\f216";
@fa-var-skype: "\f17e";
@fa-var-slack: "\f198";
@fa-var-sliders: "\f1de";
@fa-var-slideshare: "\f1e7";
@fa-var-smile-o: "\f118";
@fa-var-snapchat: "\f2ab";
@fa-var-snapchat-ghost: "\f2ac";
@fa-var-snapchat-square: "\f2ad";
@fa-var-snowflake-o: "\f2dc";
@fa-var-soccer-ball-o: "\f1e3";
@fa-var-sort: "\f0dc";
@fa-var-sort-alpha-asc: "\f15d";
@fa-var-sort-alpha-desc: "\f15e";
@fa-var-sort-amount-asc: "\f160";
@fa-var-sort-amount-desc: "\f161";
@fa-var-sort-asc: "\f0de";
@fa-var-sort-desc: "\f0dd";
@fa-var-sort-down: "\f0dd";
@fa-var-sort-numeric-asc: "\f162";
@fa-var-sort-numeric-desc: "\f163";
@fa-var-sort-up: "\f0de";
@fa-var-soundcloud: "\f1be";
@fa-var-space-shuttle: "\f197";
@fa-var-spinner: "\f110";
@fa-var-spoon: "\f1b1";
@fa-var-spotify: "\f1bc";
@fa-var-square: "\f0c8";
@fa-var-square-o: "\f096";
@fa-var-stack-exchange: "\f18d";
@fa-var-stack-overflow: "\f16c";
@fa-var-star: "\f005";
@fa-var-star-half: "\f089";
@fa-var-star-half-empty: "\f123";
@fa-var-star-half-full: "\f123";
@fa-var-star-half-o: "\f123";
@fa-var-star-o: "\f006";
@fa-var-steam: "\f1b6";
@fa-var-steam-square: "\f1b7";
@fa-var-step-backward: "\f048";
@fa-var-step-forward: "\f051";
@fa-var-stethoscope: "\f0f1";
@fa-var-sticky-note: "\f249";
@fa-var-sticky-note-o: "\f24a";
@fa-var-stop: "\f04d";
@fa-var-stop-circle: "\f28d";
@fa-var-stop-circle-o: "\f28e";
@fa-var-street-view: "\f21d";
@fa-var-strikethrough: "\f0cc";
@fa-var-stumbleupon: "\f1a4";
@fa-var-stumbleupon-circle: "\f1a3";
@fa-var-subscript: "\f12c";
@fa-var-subway: "\f239";
@fa-var-suitcase: "\f0f2";
@fa-var-sun-o: "\f185";
@fa-var-superpowers: "\f2dd";
@fa-var-superscript: "\f12b";
@fa-var-support: "\f1cd";
@fa-var-table: "\f0ce";
@fa-var-tablet: "\f10a";
@fa-var-tachometer: "\f0e4";
@fa-var-tag: "\f02b";
@fa-var-tags: "\f02c";
@fa-var-tasks: "\f0ae";
@fa-var-taxi: "\f1ba";
@fa-var-telegram: "\f2c6";
@fa-var-television: "\f26c";
@fa-var-tencent-weibo: "\f1d5";
@fa-var-terminal: "\f120";
@fa-var-text-height: "\f034";
@fa-var-text-width: "\f035";
@fa-var-th: "\f00a";
@fa-var-th-large: "\f009";
@fa-var-th-list: "\f00b";
@fa-var-themeisle: "\f2b2";
@fa-var-thermometer: "\f2c7";
@fa-var-thermometer-0: "\f2cb";
@fa-var-thermometer-1: "\f2ca";
@fa-var-thermometer-2: "\f2c9";
@fa-var-thermometer-3: "\f2c8";
@fa-var-thermometer-4: "\f2c7";
@fa-var-thermometer-empty: "\f2cb";
@fa-var-thermometer-full: "\f2c7";
@fa-var-thermometer-half: "\f2c9";
@fa-var-thermometer-quarter: "\f2ca";
@fa-var-thermometer-three-quarters: "\f2c8";
@fa-var-thumb-tack: "\f08d";
@fa-var-thumbs-down: "\f165";
@fa-var-thumbs-o-down: "\f088";
@fa-var-thumbs-o-up: "\f087";
@fa-var-thumbs-up: "\f164";
@fa-var-ticket: "\f145";
@fa-var-times: "\f00d";
@fa-var-times-circle: "\f057";
@fa-var-times-circle-o: "\f05c";
@fa-var-times-rectangle: "\f2d3";
@fa-var-times-rectangle-o: "\f2d4";
@fa-var-tint: "\f043";
@fa-var-toggle-down: "\f150";
@fa-var-toggle-left: "\f191";
@fa-var-toggle-off: "\f204";
@fa-var-toggle-on: "\f205";
@fa-var-toggle-right: "\f152";
@fa-var-toggle-up: "\f151";
@fa-var-trademark: "\f25c";
@fa-var-train: "\f238";
@fa-var-transgender: "\f224";
@fa-var-transgender-alt: "\f225";
@fa-var-trash: "\f1f8";
@fa-var-trash-o: "\f014";
@fa-var-tree: "\f1bb";
@fa-var-trello: "\f181";
@fa-var-tripadvisor: "\f262";
@fa-var-trophy: "\f091";
@fa-var-truck: "\f0d1";
@fa-var-try: "\f195";
@fa-var-tty: "\f1e4";
@fa-var-tumblr: "\f173";
@fa-var-tumblr-square: "\f174";
@fa-var-turkish-lira: "\f195";
@fa-var-tv: "\f26c";
@fa-var-twitch: "\f1e8";
@fa-var-twitter: "\f099";
@fa-var-twitter-square: "\f081";
@fa-var-umbrella: "\f0e9";
@fa-var-underline: "\f0cd";
@fa-var-undo: "\f0e2";
@fa-var-universal-access: "\f29a";
@fa-var-university: "\f19c";
@fa-var-unlink: "\f127";
@fa-var-unlock: "\f09c";
@fa-var-unlock-alt: "\f13e";
@fa-var-unsorted: "\f0dc";
@fa-var-upload: "\f093";
@fa-var-usb: "\f287";
@fa-var-usd: "\f155";
@fa-var-user: "\f007";
@fa-var-user-circle: "\f2bd";
@fa-var-user-circle-o: "\f2be";
@fa-var-user-md: "\f0f0";
@fa-var-user-o: "\f2c0";
@fa-var-user-plus: "\f234";
@fa-var-user-secret: "\f21b";
@fa-var-user-times: "\f235";
@fa-var-users: "\f0c0";
@fa-var-vcard: "\f2bb";
@fa-var-vcard-o: "\f2bc";
@fa-var-venus: "\f221";
@fa-var-venus-double: "\f226";
@fa-var-venus-mars: "\f228";
@fa-var-viacoin: "\f237";
@fa-var-viadeo: "\f2a9";
@fa-var-viadeo-square: "\f2aa";
@fa-var-video-camera: "\f03d";
@fa-var-vimeo: "\f27d";
@fa-var-vimeo-square: "\f194";
@fa-var-vine: "\f1ca";
@fa-var-vk: "\f189";
@fa-var-volume-control-phone: "\f2a0";
@fa-var-volume-down: "\f027";
@fa-var-volume-off: "\f026";
@fa-var-volume-up: "\f028";
@fa-var-warning: "\f071";
@fa-var-wechat: "\f1d7";
@fa-var-weibo: "\f18a";
@fa-var-weixin: "\f1d7";
@fa-var-whatsapp: "\f232";
@fa-var-wheelchair: "\f193";
@fa-var-wheelchair-alt: "\f29b";
@fa-var-wifi: "\f1eb";
@fa-var-wikipedia-w: "\f266";
@fa-var-window-close: "\f2d3";
@fa-var-window-close-o: "\f2d4";
@fa-var-window-maximize: "\f2d0";
@fa-var-window-minimize: "\f2d1";
@fa-var-window-restore: "\f2d2";
@fa-var-windows: "\f17a";
@fa-var-won: "\f159";
@fa-var-wordpress: "\f19a";
@fa-var-wpbeginner: "\f297";
@fa-var-wpexplorer: "\f2de";
@fa-var-wpforms: "\f298";
@fa-var-wrench: "\f0ad";
@fa-var-xing: "\f168";
@fa-var-xing-square: "\f169";
@fa-var-y-combinator: "\f23b";
@fa-var-y-combinator-square: "\f1d4";
@fa-var-yahoo: "\f19e";
@fa-var-yc: "\f23b";
@fa-var-yc-square: "\f1d4";
@fa-var-yelp: "\f1e9";
@fa-var-yen: "\f157";
@fa-var-yoast: "\f2b1";
@fa-var-youtube: "\f167";
@fa-var-youtube-play: "\f16a";
@fa-var-youtube-square: "\f166";


<?xml version="1.0" encoding="UTF-8"?>
<gui>
    <DefineStyle name="random-button" color="blue" font-size="30" margin-left="20" margin-right="20"/>
    <Image src="images/mainmenu/newgame_back.png" resizable="yes"/>
    <!-- Split window into title/top - contents and bottom/buttons area -->
    <TableLayout rows="3" cols="1">
        <rowsize row="1" relative="3"/>
        <rowsize row="2" relative="13"/>
        <rowsize row="3" relative="2"/>

        <cell row="1" col="1">
        <TableLayout rows="2" cols="1">
            <rowsize row="1" relative="2"/>
            <rowsize row="2" relative="1"/>

            <cell row="1" col="1">
            <Paragraph style="menutitle" translatable="yes">New Game</Paragraph>
            </cell>

            <cell row="2" col="1">
            <Paragraph style="listtitle" translatable="yes">
            Choose Scenario</Paragraph>
            </cell>
        </TableLayout>
        </cell>

        <cell row="2" col="1">
        <TableLayout rows="12" cols="3">
            <colsize col="1" relative="4"/>
            <colsize col="2" relative="10"/>
            <colsize col="3" relative="15"/>
            <rowsize row="6" relative="0.25"/><!-- gap between random and static scenarios-->

            <!-- put scenario list in here
            <cell row="N" col="2">

            </cell>
            -->
            <cell row="1" col="2">
<!--
            <CheckButton name="RandomEmpty">
            <text-caption style="button">Newgame 1234567890</text-caption>
            <image src="images/gui/buttons/randombutton.png"/>
            <image-hover src="images/gui/buttons/randombutton-hover.png"/>
            <image-clicked src="images/gui/buttons/randombutton-clicked.png"/>
            <image-checked src="images/gui/buttons/randombutton-checked.png"/>
            </CheckButton>
            -->
                <TableLayout rows="2" cols="2">
                    <cell row="1" col="1">
                    <Paragraph style="listtitle" translatable="yes">Village</Paragraph>
                    </cell>
                    <cell row="1" col="2">
                        <CheckButton name="WithVillage">
                            <image src="images/gui/checkbox/checkbox.png"/>
                            <image-checked src="images/gui/checkbox/checkbox_checked.png"/>
                        </CheckButton>
                    </cell>
                    <cell row="2" col="1">
                    <Paragraph style="listtitle" translatable="yes">Without trees</Paragraph>
                    </cell>
                    <cell row="2" col="2">
                        <CheckButton name="WithoutTrees">
                            <image src="images/gui/checkbox/checkbox.png"/>
                            <image-checked src="images/gui/checkbox/checkbox_checked.png"/>
                        </CheckButton>
                    </cell>
                </TableLayout>
            </cell>
            <cell row="2" col="2">
            <CheckButton name="RiverDelta">
            <text-caption style="random-button">Newgame 1234567890</text-caption>
            <image src="images/gui/buttons/randombutton.png"/>
            <image-hover src="images/gui/buttons/randombutton-hover.png"/>
            <image-clicked src="images/gui/buttons/randombutton-clicked.png"/>
            <image-checked src="images/gui/buttons/randombutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="3" col="2">
            <CheckButton name="DesertArea">
            <text-caption style="random-button">Newgame 1234567890</text-caption>
            <image src="images/gui/buttons/randombutton.png"/>
            <image-hover src="images/gui/buttons/randombutton-hover.png"/>
            <image-clicked src="images/gui/buttons/randombutton-clicked.png"/>
            <image-checked src="images/gui/buttons/randombutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="4" col="2">
            <CheckButton name="TemperateArea">
            <text-caption style="random-button">Newgame 1234567890</text-caption>
            <image src="images/gui/buttons/randombutton.png"/>
            <image-hover src="images/gui/buttons/randombutton-hover.png"/>
            <image-clicked src="images/gui/buttons/randombutton-clicked.png"/>
            <image-checked src="images/gui/buttons/randombutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="5" col="2">
            <CheckButton name="SwampArea">
            <text-caption style="random-button">Newgame 1234567890</text-caption>
            <image src="images/gui/buttons/randombutton.png"/>
            <image-hover src="images/gui/buttons/randombutton-hover.png"/>
            <image-clicked src="images/gui/buttons/randombutton-clicked.png"/>
            <image-checked src="images/gui/buttons/randombutton-checked.png"/>
            </CheckButton>
            </cell>

            <!-- row 6 is the gap between random and static scenarios-->

            <cell row="7" col="2">
            <CheckButton name="File0">
            <text-caption style="button">Savegame 1234567890</text-caption>
            <image src="images/gui/buttons/savebutton.png"/>
            <image-hover src="images/gui/buttons/savebutton-hover.png"/>
            <image-clicked src="images/gui/buttons/savebutton-clicked.png"/>
            <image-checked src="images/gui/buttons/savebutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="8" col="2">
            <CheckButton name="File1">
            <text-caption style="button">Savegame 1234567890</text-caption>
            <image src="images/gui/buttons/savebutton.png"/>
            <image-hover src="images/gui/buttons/savebutton-hover.png"/>
            <image-clicked src="images/gui/buttons/savebutton-clicked.png"/>
            <image-checked src="images/gui/buttons/savebutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="9" col="2">
            <CheckButton name="File2">
            <text-caption style="button">Savegame 1234567890</text-caption>
            <image src="images/gui/buttons/savebutton.png"/>
            <image-hover src="images/gui/buttons/savebutton-hover.png"/>
            <image-clicked src="images/gui/buttons/savebutton-clicked.png"/>
            <image-checked src="images/gui/buttons/savebutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="10" col="2">
            <CheckButton name="File3">
            <text-caption style="button">Savegame 1234567890</text-caption>
            <image src="images/gui/buttons/savebutton.png"/>
            <image-hover src="images/gui/buttons/savebutton-hover.png"/>
            <image-clicked src="images/gui/buttons/savebutton-clicked.png"/>
            <image-checked src="images/gui/buttons/savebutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="11" col="2">
            <CheckButton name="File4">
            <text-caption style="button">Savegame 1234567890</text-caption>
            <image src="images/gui/buttons/savebutton.png"/>
            <image-hover src="images/gui/buttons/savebutton-hover.png"/>
            <image-clicked src="images/gui/buttons/savebutton-clicked.png"/>
            <image-checked src="images/gui/buttons/savebutton-checked.png"/>
            </CheckButton>
            </cell>
            <cell row="12" col="2">
            <CheckButton name="File5">
            <text-caption style="button">Savegame 1234567890</text-caption>
            <image src="images/gui/buttons/savebutton.png"/>
            <image-hover src="images/gui/buttons/savebutton-hover.png"/>
            <image-clicked src="images/gui/buttons/savebutton-clicked.png"/>
            <image-checked src="images/gui/buttons/savebutton-checked.png"/>
            </CheckButton>
            </cell>
        </TableLayout>
        </cell>
        <cell row="3" col="1">
        <TableLayout rows="2" cols="2">
            <rowsize row="1" relative="1"/>
            <rowsize row="2" relative="3"/>
            <cell row="2" col="1" halign="left">
            <Button name="BackButton">
                <text-caption style="button" translatable="yes">Back</text-caption>
                <image src="images/mainmenu/buttons/back.png"/>
                <image-hover src="images/mainmenu/buttons/back-hover.png"/>
                <image-clicked src="images/mainmenu/buttons/back-clicked.png"/>
            </Button>
            </cell>
            <cell row="2" col="2" halign="right">
            <Button name="StartButton">
                <text-caption style="button" translatable="yes">Start</text-caption>
                <image src="images/mainmenu/buttons/start.png"/>
                <image-hover src="images/mainmenu/buttons/start-hover.png"/>
                <image-clicked src="images/mainmenu/buttons/start-clicked.png"/>
            </Button>
            </cell>
        </TableLayout>
        </cell>
    </TableLayout>
</gui>


/*
 * Copyright (C) 2006 TopCoder Inc., All Rights Reserved.
 */
package com.topcoder.uml.actions.model.classifiers;

/**
 *

 * This class extends from RemoveAction and used for removing Class instance
 * from model or namespace. Its methods provide only proper configuration and
 * presentation of action. All logic represent into its super class. Also it
 * provide checking if given Class instance is exception.
 *

 *

 * Thread-safety: Class is not thread safety because it extends from mutable
 * class.
 *

 *
 * @author tushak, TCSDEVELOPER
 * @version 1.0
 */
public class RemoveExceptionAction extends RemoveAction {

    /**
     *

     * Represent human readable description of action.
     *

     */
    private static final String PRESENTATION_NAME = "Remove Exception";

    /**
     *

     * Constructor which provides configuration for current action.
     *

     *
     * @param exception
     *            Class instance, null impossible
     * @throws IllegalArgumentException
     *             when exception is null
     * @throws InvalidDataConteneException
     *             if given class is not exception
     */
    public RemoveExceptionAction(com.topcoder.uml.model.core.classifiers.Class exception)
            throws InvalidDataContentException {
        super(exception, new ExceptionUtil());

        ExceptionUtil util = (ExceptionUtil) getClassToolUtil();

        if (!util.isException(exception)) {
            throw new InvalidDataContentException("Given class is not exception.");
        }
    }

    /**
     *

     * Return PRESENTATION_NAME attribute - human readable description of
     * action.
     *

     *
     * @return PRESENTATION_NAME attribute
     */
    public String getPresentationName() {
        return PRESENTATION_NAME;
    }
}


//
//  UIDevice+Hardware.m
//  TestTable
//
//  Created by Inder Kumar Rathore on 19/01/13.
//  Copyright (c) 2013 Rathore. All rights reserved.
//

#import "UIDevice+Hardware.h"
#include <sys/types.h>
#include <sys/sysctl.h>

#import <sys/socket.h>
#import <sys/param.h>
#import <sys/mount.h>
#import <sys/stat.h>
#import <sys/utsname.h>
#import <net/if.h>
#import <net/if_dl.h>
#import <mach/mach.h>
#import <mach/mach_host.h>
#import <mach/processor_info.h>

@implementation UIDevice (Hardware)
- (NSString*)hardwareString {
    int name[] = {CTL_HW,HW_MACHINE};
    size_t size = 100;
    sysctl(name, 2, NULL, &size, NULL, 0); // getting size of answer
    char *hw_machine = malloc(size);

    sysctl(name, 2, hw_machine, &size, NULL, 0);
    NSString *hardware = [NSString stringWithUTF8String:hw_machine];
    free(hw_machine);
    return hardware;
}

/* This is another way of gtting the system info
 * For this you have to #import <sys/utsname.h>
 */

/*
 NSString* machineName
 {
 struct utsname systemInfo;
 uname(&systemInfo);
 return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
 }
 */

- (Hardware)hardware {
    NSString *hardware = [self hardwareString];
    if ([hardware isEqualToString:@"iPhone1,1"])    return IPHONE_2G;
    if ([hardware isEqualToString:@"iPhone1,2"])    return IPHONE_3G;
    if ([hardware isEqualToString:@"iPhone2,1"])    return IPHONE_3GS;
    if ([hardware isEqualToString:@"iPhone3,1"])    return IPHONE_4;
    if ([hardware isEqualToString:@"iPhone3,2"])    return IPHONE_4;
    if ([hardware isEqualToString:@"iPhone3,3"])    return IPHONE_4_CDMA;
    if ([hardware isEqualToString:@"iPhone4,1"])    return IPHONE_4S;
    if ([hardware isEqualToString:@"iPhone5,1"])    return IPHONE_5;
    if ([hardware isEqualToString:@"iPhone5,2"])    return IPHONE_5_CDMA_GSM;
    if ([hardware isEqualToString:@"iPhone5,3"])    return IPHONE_5C;
    if ([hardware isEqualToString:@"iPhone5,4"])    return IPHONE_5C_CDMA_GSM;
    if ([hardware isEqualToString:@"iPhone6,1"])    return IPHONE_5S;
    if ([hardware isEqualToString:@"iPhone6,2"])    return IPHONE_5S_CDMA_GSM;

    if ([hardware isEqualToString:@"iPhone7,1"])    return IPHONE_6_PLUS;
    if ([hardware isEqualToString:@"iPhone7,2"])    return IPHONE_6;

    if ([hardware isEqualToString:@"iPod1,1"])      return IPOD_TOUCH_1G;
    if ([hardware isEqualToString:@"iPod2,1"])      return IPOD_TOUCH_2G;
    if ([hardware isEqualToString:@"iPod3,1"])      return IPOD_TOUCH_3G;
    if ([hardware isEqualToString:@"iPod4,1"])      return IPOD_TOUCH_4G;
    if ([hardware isEqualToString:@"iPod5,1"])      return IPOD_TOUCH_5G;

    if ([hardware isEqualToString:@"iPad1,1"])      return IPAD;
    if ([hardware isEqualToString:@"iPad1,2"])      return IPAD_3G;
    if ([hardware isEqualToString:@"iPad2,1"])      return IPAD_2_WIFI;
    if ([hardware isEqualToString:@"iPad2,2"])      return IPAD_2;
    if ([hardware isEqualToString:@"iPad2,3"])      return IPAD_2_CDMA;
    if ([hardware isEqualToString:@"iPad2,4"])      return IPAD_2;
    if ([hardware isEqualToString:@"iPad2,5"])      return IPAD_MINI_WIFI;
    if ([hardware isEqualToString:@"iPad2,6"])      return IPAD_MINI;
    if ([hardware isEqualToString:@"iPad2,7"])      return IPAD_MINI_WIFI_CDMA;
    if ([hardware isEqualToString:@"iPad3,1"])      return IPAD_3_WIFI;
    if ([hardware isEqualToString:@"iPad3,2"])      return IPAD_3_WIFI_CDMA;
    if ([hardware isEqualToString:@"iPad3,3"])      return IPAD_3;
    if ([hardware isEqualToString:@"iPad3,4"])      return IPAD_4_WIFI;
    if ([hardware isEqualToString:@"iPad3,5"])      return IPAD_4;
    if ([hardware isEqualToString:@"iPad3,6"])      return IPAD_4_GSM_CDMA;
    if ([hardware isEqualToString:@"iPad4,1"])      return IPAD_AIR_WIFI;
    if ([hardware isEqualToString:@"iPad4,2"])      return IPAD_AIR_WIFI_GSM;
    if ([hardware isEqualToString:@"iPad4,3"])      return IPAD_AIR_WIFI_CDMA;
    if ([hardware isEqualToString:@"iPad4,4"])      return IPAD_MINI_RETINA_WIFI;
    if ([hardware isEqualToString:@"iPad4,5"])      return IPAD_MINI_RETINA_WIFI_CDMA;

    if ([hardware isEqualToString:@"i386"])         return SIMULATOR;
    if ([hardware isEqualToString:@"x86_64"])       return SIMULATOR;
    return NOT_AVAILABLE;
}

- (NSString*)hardwareDescription {
    NSString *hardware = [self hardwareString];
    if ([hardware isEqualToString:@"iPhone1,1"])    return @"iPhone 2G";
    if ([hardware isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([hardware isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([hardware isEqualToString:@"iPhone3,1"])    return @"iPhone 4 (GSM)";
    if ([hardware isEqualToString:@"iPhone3,2"])    return @"iPhone 4 (GSM Rev. A)";
    if ([hardware isEqualToString:@"iPhone3,3"])    return @"iPhone 4 (CDMA)";
    if ([hardware isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([hardware isEqualToString:@"iPhone5,1"])    return @"iPhone 5 (GSM)";
    if ([hardware isEqualToString:@"iPhone5,2"])    return @"iPhone 5 (Global)";
    if ([hardware isEqualToString:@"iPhone5,3"])    return @"iPhone 5C (GSM)";
    if ([hardware isEqualToString:@"iPhone5,4"])    return @"iPhone 5C (Global)";
    if ([hardware isEqualToString:@"iPhone6,1"])    return @"iPhone 5S (GSM)";
    if ([hardware isEqualToString:@"iPhone6,2"])    return @"iPhone 5S (Global)";

    if ([hardware isEqualToString:@"iPhone7,1"])    return @"iPhone 6 Plus";
    if ([hardware isEqualToString:@"iPhone7,2"])    return @"iPhone 6";

    if ([hardware isEqualToString:@"iPod1,1"])      return @"iPod Touch (1 Gen)";
    if ([hardware isEqualToString:@"iPod2,1"])      return @"iPod Touch (2 Gen)";
    if ([hardware isEqualToString:@"iPod3,1"])      return @"iPod Touch (3 Gen)";
    if ([hardware isEqualToString:@"iPod4,1"])      return @"iPod Touch (4 Gen)";
    if ([hardware isEqualToString:@"iPod5,1"])      return @"iPod Touch (5 Gen)";

    if ([hardware isEqualToString:@"iPad1,1"])      return @"iPad (WiFi)";
    if ([hardware isEqualToString:@"iPad1,2"])      return @"iPad 3G";
    if ([hardware isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([hardware isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([hardware isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([hardware isEqualToString:@"iPad2,4"])      return @"iPad 2 (WiFi Rev. A)";
    if ([hardware isEqualToString:@"iPad2,5"])      return @"iPad Mini (WiFi)";
    if ([hardware isEqualToString:@"iPad2,6"])      return @"iPad Mini (GSM)";
    if ([hardware isEqualToString:@"iPad2,7"])      return @"iPad Mini (CDMA)";
    if ([hardware isEqualToString:@"iPad3,1"])      return @"iPad 3 (WiFi)";
    if ([hardware isEqualToString:@"iPad3,2"])      return @"iPad 3 (CDMA)";
    if ([hardware isEqualToString:@"iPad3,3"])      return @"iPad 3 (Global)";
    if ([hardware isEqualToString:@"iPad3,4"])      return @"iPad 4 (WiFi)";
    if ([hardware isEqualToString:@"iPad3,5"])      return @"iPad 4 (CDMA)";
    if ([hardware isEqualToString:@"iPad3,6"])      return @"iPad 4 (Global)";
    if ([hardware isEqualToString:@"iPad4,1"])      return @"iPad Air (WiFi)";
    if ([hardware isEqualToString:@"iPad4,2"])      return @"iPad Air (WiFi+GSM)";
    if ([hardware isEqualToString:@"iPad4,3"])      return @"iPad Air (WiFi+CDMA)";
    if ([hardware isEqualToString:@"iPad4,4"])      return @"iPad Mini Retina (WiFi)";
    if ([hardware isEqualToString:@"iPad4,5"])      return @"iPad Mini Retina (WiFi+CDMA)";
    if ([hardware isEqualToString:@"i386"])         return @"Simulator";
    if ([hardware isEqualToString:@"x86_64"])       return @"Simulator";

    NSLog(@"This is a device which is not listed in this category. Please visit https://github.com/inderkumarrathore/UIDevice-Hardware and add a comment there.");
    NSLog(@"Your device hardware string is: %@", hardware);
    if ([hardware hasPrefix:@"iPhone"]) return @"iPhone";
    if ([hardware hasPrefix:@"iPod"]) return @"iPod";
    if ([hardware hasPrefix:@"iPad"]) return @"iPad";
    return nil;
}

- (NSString*)hardwareSimpleDescription
{
    NSString *hardware = [self hardwareString];
    if ([hardware isEqualToString:@"iPhone1,1"])    return @"iPhone 2G";
    if ([hardware isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([hardware isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([hardware isEqualToString:@"iPhone3,1"])    return @"iPhone 4";
    if ([hardware isEqualToString:@"iPhone3,2"])    return @"iPhone 4";
    if ([hardware isEqualToString:@"iPhone3,3"])    return @"iPhone 4";
    if ([hardware isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([hardware isEqualToString:@"iPhone5,1"])    return @"iPhone 5";
    if ([hardware isEqualToString:@"iPhone5,2"])    return @"iPhone 5";
    if ([hardware isEqualToString:@"iPhone5,3"])    return @"iPhone 5C";
    if ([hardware isEqualToString:@"iPhone5,4"])    return @"iPhone 5C";
    if ([hardware isEqualToString:@"iPhone6,1"])    return @"iPhone 5S";
    if ([hardware isEqualToString:@"iPhone6,2"])    return @"iPhone 5S";

    if ([hardware isEqualToString:@"iPod1,1"])      return @"iPod Touch (1 Gen)";
    if ([hardware isEqualToString:@"iPod2,1"])      return @"iPod Touch (2 Gen)";
    if ([hardware isEqualToString:@"iPod3,1"])      return @"iPod Touch (3 Gen)";
    if ([hardware isEqualToString:@"iPod4,1"])      return @"iPod Touch (4 Gen)";
    if ([hardware isEqualToString:@"iPod5,1"])      return @"iPod Touch (5 Gen)";

    if ([hardware isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([hardware isEqualToString:@"iPad1,2"])      return @"iPad";
    if ([hardware isEqualToString:@"iPad2,1"])      return @"iPad 2";
    if ([hardware isEqualToString:@"iPad2,2"])      return @"iPad 2";
    if ([hardware isEqualToString:@"iPad2,3"])      return @"iPad 2";
    if ([hardware isEqualToString:@"iPad2,4"])      return @"iPad 2";
    if ([hardware isEqualToString:@"iPad2,5"])      return @"iPad Mini";
    if ([hardware isEqualToString:@"iPad2,6"])      return @"iPad Mini";
    if ([hardware isEqualToString:@"iPad2,7"])      return @"iPad Mini";
    if ([hardware isEqualToString:@"iPad3,1"])      return @"iPad 3";
    if ([hardware isEqualToString:@"iPad3,2"])      return @"iPad 3";
    if ([hardware isEqualToString:@"iPad3,3"])      return @"iPad 3";
    if ([hardware isEqualToString:@"iPad3,4"])      return @"iPad 4";
    if ([hardware isEqualToString:@"iPad3,5"])      return @"iPad 4";
    if ([hardware isEqualToString:@"iPad3,6"])      return @"iPad 4";
    if ([hardware isEqualToString:@"iPad4,1"])      return @"iPad Air";
    if ([hardware isEqualToString:@"iPad4,2"])      return @"iPad Air";
    if ([hardware isEqualToString:@"iPad4,3"])      return @"iPad Air";
    if ([hardware isEqualToString:@"iPad4,4"])      return @"iPad Mini Retina";
    if ([hardware isEqualToString:@"iPad4,5"])      return @"iPad Mini Retina";

    if ([hardware isEqualToString:@"i386"])         return @"Simulator";
    if ([hardware isEqualToString:@"x86_64"])       return @"Simulator";

    NSLog(@"This is a device which is not listed in this category. Please visit https://github.com/inderkumarrathore/UIDevice-Hardware and add a comment there.");
    NSLog(@"Your device hardware string is: %@", hardware);

    if ([hardware hasPrefix:@"iPhone"]) return @"iPhone";
    if ([hardware hasPrefix:@"iPod"]) return @"iPod";
    if ([hardware hasPrefix:@"iPad"]) return @"iPad";

    return nil;
}

- (float)hardwareNumber:(Hardware)hardware {
    switch (hardware) {
        case IPHONE_2G: return 1.1f;
        case IPHONE_3G: return 1.2f;
        case IPHONE_3GS: return 2.1f;
        case IPHONE_4:    return 3.1f;
        case IPHONE_4_CDMA:    return 3.3f;
        case IPHONE_4S:    return 4.1f;
        case IPHONE_5:    return 5.1f;
        case IPHONE_5_CDMA_GSM:    return 5.2f;
        case IPHONE_5C:    return 5.3f;
        case IPHONE_5C_CDMA_GSM:    return 5.4f;
        case IPHONE_5S:    return 6.1f;
        case IPHONE_5S_CDMA_GSM:    return 6.2f;

        case IPHONE_6:         return 7.2f;
        case IPHONE_6_PLUS:    return 7.1f;

        case IPOD_TOUCH_1G:    return 1.1f;
        case IPOD_TOUCH_2G:    return 2.1f;
        case IPOD_TOUCH_3G:    return 3.1f;
        case IPOD_TOUCH_4G:    return 4.1f;
        case IPOD_TOUCH_5G:    return 5.1f;

        case IPAD:    return 1.1f;
        case IPAD_3G:    return 1.2f;
        case IPAD_2_WIFI:    return 2.1f;
        case IPAD_2:    return 2.2f;
        case IPAD_2_CDMA:    return 2.3f;
        case IPAD_MINI_WIFI:    return 2.5f;
        case IPAD_MINI:    return 2.6f;
        case IPAD_MINI_WIFI_CDMA:    return 2.7f;
        case IPAD_3_WIFI:    return 3.1f;
        case IPAD_3_WIFI_CDMA:    return 3.2f;
        case IPAD_3:    return 3.3f;
        case IPAD_4_WIFI:    return 3.4f;
        case IPAD_4:    return 3.5f;
        case IPAD_4_GSM_CDMA:    return 3.6f;
        case IPAD_AIR_WIFI:    return 4.1f;
        case IPAD_AIR_WIFI_GSM:    return 4.2f;
        case IPAD_AIR_WIFI_CDMA:    return 4.3f;
        case IPAD_MINI_RETINA_WIFI:    return 4.4f;
        case IPAD_MINI_RETINA_WIFI_CDMA:    return 4.5f;

        case SIMULATOR:    return 100.0f;
        case NOT_AVAILABLE:    return 200.0f;
    }
    return 200.0f; //Device is not available
}

- (BOOL)isCurrentDeviceHardwareBetterThan:(Hardware)hardware {
    float otherHardware = [self hardwareNumber:hardware];
    float currentHardware = [self hardwareNumber:[self hardware]];
    return currentHardware >= otherHardware;
}

- (CGSize)backCameraStillImageResolutionInPixels
{
    switch ([self hardware]) {
        case IPHONE_2G:
        case IPHONE_3G:
            return CGSizeMake(1600, 1200);
            break;
        case IPHONE_3GS:
            return CGSizeMake(2048, 1536);
            break;
        case IPHONE_4:
        case IPHONE_4_CDMA:
        case IPAD_3_WIFI:
        case IPAD_3_WIFI_CDMA:
        case IPAD_3:
        case IPAD_4_WIFI:
        case IPAD_4:
        case IPAD_4_GSM_CDMA:
            return CGSizeMake(2592, 1936);
            break;
        case IPHONE_4S:
        case IPHONE_5:
        case IPHONE_5_CDMA_GSM:
        case IPHONE_5C:
        case IPHONE_5C_CDMA_GSM:
            return CGSizeMake(3264, 2448);
            break;

        case IPOD_TOUCH_4G:
            return CGSizeMake(960, 720);
            break;
        case IPOD_TOUCH_5G:
            return CGSizeMake(2440, 1605);
            break;

        case IPAD_2_WIFI:
        case IPAD_2:
        case IPAD_2_CDMA:
            return CGSizeMake(872, 720);
            break;

        case IPAD_MINI_WIFI:
        case IPAD_MINI:
        case IPAD_MINI_WIFI_CDMA:
            return CGSizeMake(1820, 1304);
            break;
        default:
            NSLog(@"We have no resolution for your device's camera listed in this category. Please, make photo with back camera of your device, get its resolution in pixels (via Preview Cmd+I for example) and add a comment to this repository on GitHub.com in format Device = Hpx x Wpx.");
            NSLog(@"Your device is: %@", [self hardwareDescription]);
            break;
    }
    return CGSizeZero;
}

- (BOOL)isIphoneWith4inchDisplay
{
    if (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone) {
        double height = [[UIScreen mainScreen] bounds].size.height;
        if (fabs(height-568.0f) < DBL_EPSILON) {
            return YES;
        }
    }
    return NO;
}

+ (NSString *)macAddress {
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;

    if((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. Rrror!\n");
        return NULL;
    }

    if(sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
                           *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);

    return outstring;
}

+ (NSString *)systemVersion
{
    return [[UIDevice currentDevice] systemVersion];
}
+ (BOOL)hasCamera
{
    return [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
}
#pragma mark - sysctl utils

+ (NSUInteger)getSysInfo:(uint)typeSpecifier
{
    size_t size = sizeof(int);
    int result;
    int mib[2] = {CTL_HW, typeSpecifier};
    sysctl(mib, 2, &result, &size, NULL, 0);
    return (NSUInteger)result;
}

#pragma mark - memory information
+ (NSUInteger)cpuFrequency {
    return [self getSysInfo:HW_CPU_FREQ];
}

+ (NSUInteger)busFrequency {
    return [self getSysInfo:HW_BUS_FREQ];
}

+ (NSUInteger)ramSize {
    return [self getSysInfo:HW_MEMSIZE];
}

+ (NSUInteger)cpuNumber {
    return [self getSysInfo:HW_NCPU];
}

+ (NSUInteger)totalMemoryBytes
{
    return [self getSysInfo:HW_PHYSMEM];
}

+ (NSUInteger)freeMemoryBytes
{
    mach_port_t host_port = mach_host_self();
    mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    vm_size_t pagesize;
    vm_statistics_data_t vm_stat;

    host_page_size(host_port, &pagesize);
    if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
        return 0;
    }
    unsigned long mem_free = vm_stat.free_count * pagesize;
    return mem_free;
}

#pragma mark - disk information

+ (long long)freeDiskSpaceBytes
{
    struct statfs buf;
    long long freespace;
    freespace = 0;
    if ( statfs("/private/var", &buf) >= 0 ) {
        freespace = (long long)buf.f_bsize * buf.f_bfree;
    }
    return freespace;
}

+ (long long)totalDiskSpaceBytes
{
    struct statfs buf;
    long long totalspace;
    totalspace = 0;
    if ( statfs("/private/var", &buf) >= 0 ) {
        totalspace = (long long)buf.f_bsize * buf.f_blocks;
    }
    return totalspace;
}
@end


/* Whole cell */
div.container.cell {
  padding-left: 0;
  margin-bottom: 1em;
}

/* Removing all background formatting so we can control at the div level */
.cell_input div.highlight, .cell_input pre, .cell_output .output * {
  border: none;
  background-color: transparent;
  box-shadow: none;
}

.cell_output .output pre, .cell_input pre {
  margin: 0px;
}

/* Input cells */
div.cell div.cell_input {
  padding-left: 0em;
  padding-right: 0em;
  border: 1px #ccc solid;
  background-color: #f7f7f7;
  border-left-color: green;
  border-left-width: medium;
}

div.cell_input > div, div.cell_output div.output > div.highlight {
  margin: 0em !important;
  border: none !important;
}

/* All cell outputs */
.cell_output {
  padding-left: 1em;
  padding-right: 0em;
  margin-top: 1em;
}

/* Outputs from jupyter_sphinx overrides to remove extra CSS */
div.section div.jupyter_container {
  padding: .4em;
  margin: 0 0 .4em 0;
  background-color: none;
  border: none;
  -moz-box-shadow: none;
  -webkit-box-shadow: none;
  box-shadow: none;
}

/* Text outputs from cells */
.cell_output .output.text_plain,
.cell_output .output.traceback,
.cell_output .output.stream,
.cell_output .output.stderr
  {
  background: #fcfcfc;
  margin-top: 1em;
  margin-bottom: 0em;
  box-shadow: none;
}

.cell_output .output.text_plain,
.cell_output .output.stream,
.cell_output .output.stderr {
  border: 1px solid #f7f7f7;
}

.cell_output .output.stderr {
  background: #fdd;
}

.cell_output .output.traceback {
  border: 1px solid #ffd6d6;
}

/* Math align to the left */
.cell_output .MathJax_Display {
  text-align: left !important;
}

/* Pandas tables. Pulled from the Jupyter / nbsphinx CSS */
div.cell_output table {
    border: none;
    border-collapse: collapse;
    border-spacing: 0;
    color: black;
    font-size: 1em;
    table-layout: fixed;
  }
  div.cell_output thead {
    border-bottom: 1px solid black;
    vertical-align: bottom;
  }
  div.cell_output tr,
  div.cell_output th,
  div.cell_output td {
    text-align: right;
    vertical-align: middle;
    padding: 0.5em 0.5em;
    line-height: normal;
    white-space: normal;
    max-width: none;
    border: none;
  }
  div.cell_output th {
    font-weight: bold;
  }
  div.cell_output tbody tr:nth-child(odd) {
    background: #f5f5f5;
  }
  div.cell_output tbody tr:hover {
    background: rgba(66, 165, 245, 0.2);
  }

/* Inline text from `paste` operation */

span.pasted-text {
  font-weight: bold;
}

span.pasted-inline img {
  max-height: 2em;
}

tbody span.pasted-inline img {
  max-height: none;
}

/* Font colors for translated ANSI escape sequences
Color values are adapted from share/jupyter/nbconvert/templates/classic/static/style.css
*/
div.highlight .-Color-Bold {
  font-weight: bold;
}
div.highlight .-Color[class*=-Black] {
  color :#3E424D
}
div.highlight .-Color[class*=-Red] {
  color: #E75C58
}
div.highlight .-Color[class*=-Green] {
  color: #00A250
}
div.highlight .-Color[class*=-Yellow] {
  color: yellow
}
div.highlight .-Color[class*=-Blue] {
  color: #208FFB
}
div.highlight .-Color[class*=-Magenta] {
  color: #D160C4
}
div.highlight .-Color[class*=-Cyan] {
  color: #60C6C8
}
div.highlight .-Color[class*=-White] {
  color: #C5C1B4
}
div.highlight .-Color[class*=-BGBlack] {
  background-color: #3E424D
}
div.highlight .-Color[class*=-BGRed] {
  background-color: #E75C58
}
div.highlight .-Color[class*=-BGGreen] {
  background-color: #00A250
}
div.highlight .-Color[class*=-BGYellow] {
  background-color: yellow
}
div.highlight .-Color[class*=-BGBlue] {
  background-color: #208FFB
}
div.highlight .-Color[class*=-BGMagenta] {
  background-color: #D160C4
}
div.highlight .-Color[class*=-BGCyan] {
  background-color: #60C6C8
}
div.highlight .-Color[class*=-BGWhite] {
  background-color: #C5C1B4
}


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle">
	<gradient android:startColor="#FFA500" android:endColor="#E0AA6E"
		android:type="linear" android:angle="90" />
	<corners android:radius="8dp" />
</shape>


/*
 * Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.query;

import com.hazelcast.internal.serialization.BinaryInterface;

import java.io.Serializable;
import java.util.Map;

/**
 * Represents a map entry predicate. Implementations of this interface are basic
 * building blocks for performing queries on map entries.
 *

 * Implementations must be thread-safe, since the {@link #apply}
 * method may be called by multiple threads concurrently.
 *
 * @param <K> the type of keys the predicate operates on.
 * @param <V> the type of values the predicate operates on.
 */
@BinaryInterface
@FunctionalInterface
public interface Predicate<K, V> extends Serializable {

    /**
     * Applies this predicate to the given map entry.
     *

     * Implementations must be thread-safe, since this method may be
     * called by multiple threads concurrently.
     *
     * @param mapEntry the map entry to apply this predicate to.
     * @return {@code true} if the given map entry matches this predicate,
     * {@code false} otherwise.
     */
    boolean apply(Map.Entry<K, V> mapEntry);

}