<commit_before>/*
 * Copyright (c) 2003-2010 Rony Shapiro <ronys@users.sourceforge.net>.
 * All rights reserved. Use of the code is allowed under the
 * Artistic License 2.0 terms, as specified in the LICENSE file
 * distributed with this code, or available from
 * http://www.opensource.org/licenses/artistic-license-2.0.php
 */

/** \file safecombinationentry.cpp
*
*/
// Generated by DialogBlocks, Sun 18 Jan 2009 09:22:13 PM IST

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

////@begin includes
////@end includes

#include "safecombinationentry.h"
#include "safecombinationsetup.h"
#include "version.h"
#include "corelib/corelib.h"
#include "corelib/PWSdirs.h"
#include "os/file.h"
////@begin XPM images
#include "../graphics/wxWidgets/cpane.xpm"
#include "../graphics/wxWidgets/psafetxt.xpm"
////@end XPM images
#include "pwsafeapp.h"
#include "SafeCombinationCtrl.h"

/*!
 * CSafeCombinationEntry type definition
 */

IMPLEMENT_CLASS( CSafeCombinationEntry, wxDialog )

/*!
 * CSafeCombinationEntry event table definition
 */

BEGIN_EVENT_TABLE( CSafeCombinationEntry, wxDialog )

////@begin CSafeCombinationEntry event table entries
  EVT_BUTTON( ID_ELLIPSIS, CSafeCombinationEntry::OnEllipsisClick )

  EVT_BUTTON( ID_NEWDB, CSafeCombinationEntry::OnNewDbClick )

  EVT_BUTTON( wxID_OK, CSafeCombinationEntry::OnOk )

  EVT_BUTTON( wxID_CANCEL, CSafeCombinationEntry::OnCancel )
////@end CSafeCombinationEntry event table entries

END_EVENT_TABLE()

/*!
 * CSafeCombinationEntry constructors
 */

CSafeCombinationEntry::CSafeCombinationEntry(PWScore &core)
: m_core(core), m_tries(0)
{
  Init();
}

CSafeCombinationEntry::CSafeCombinationEntry(wxWindow* parent, PWScore &core,
                                             wxWindowID id,
                                             const wxString& caption,
                                             const wxPoint& pos,
                                             const wxSize& size, long style)
  : m_core(core), m_tries(0)
{
  Init();
  Create(parent, id, caption, pos, size, style);
}

/*!
 * CSafeCombinationEntry creator
 */

bool CSafeCombinationEntry::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin CSafeCombinationEntry creation
  SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
  wxDialog::Create( parent, id, caption, pos, size, style );

  CreateControls();
  if (GetSizer())
  {
    GetSizer()->SetSizeHints(this);
  }
  Centre();
////@end CSafeCombinationEntry creation
  return true;
}

/*!
 * CSafeCombinationEntry destructor
 */

CSafeCombinationEntry::~CSafeCombinationEntry()
{
////@begin CSafeCombinationEntry destruction
////@end CSafeCombinationEntry destruction
}

/*!
 * Member initialisation
 */

void CSafeCombinationEntry::Init()
{
  m_readOnly = m_core.IsReadOnly();
  m_filename = m_core.GetCurFile().c_str();
////@begin CSafeCombinationEntry member initialisation
  m_version = NULL;
  m_filenameCB = NULL;
////@end CSafeCombinationEntry member initialisation
}

/*!
 * Control creation for CSafeCombinationEntry
 */

void CSafeCombinationEntry::CreateControls()
{
////@begin CSafeCombinationEntry content construction
  CSafeCombinationEntry* itemDialog1 = this;

  wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
  itemDialog1->SetSizer(itemBoxSizer2);

  wxStaticBitmap* itemStaticBitmap3 = new wxStaticBitmap( itemDialog1, wxID_STATIC, itemDialog1->GetBitmapResource(wxT("../graphics/wxWidgets/cpane.xpm")), wxDefaultPosition, itemDialog1->ConvertDialogToPixels(wxSize(49, 46)), 0 );
  itemBoxSizer2->Add(itemStaticBitmap3, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxVERTICAL);
  itemBoxSizer2->Add(itemBoxSizer4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
  itemBoxSizer4->Add(itemBoxSizer5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);

  wxStaticBitmap* itemStaticBitmap6 = new wxStaticBitmap( itemDialog1, wxID_STATIC, itemDialog1->GetBitmapResource(wxT("../graphics/wxWidgets/psafetxt.xpm")), wxDefaultPosition, itemDialog1->ConvertDialogToPixels(wxSize(111, 16)), 0 );
  itemBoxSizer5->Add(itemStaticBitmap6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  m_version = new wxStaticText( itemDialog1, wxID_STATIC, _("VX.YY"), wxDefaultPosition, wxDefaultSize, 0 );
  itemBoxSizer5->Add(m_version, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxStaticText* itemStaticText8 = new wxStaticText( itemDialog1, wxID_STATIC, _("Open Password Database:"), wxDefaultPosition, wxDefaultSize, 0 );
  itemBoxSizer4->Add(itemStaticText8, 0, wxALIGN_LEFT|wxALL, 3);

  wxBoxSizer* itemBoxSizer9 = new wxBoxSizer(wxHORIZONTAL);
  itemBoxSizer4->Add(itemBoxSizer9, 50, wxGROW|wxALL, 5);

  wxArrayString m_filenameCBStrings;
  m_filenameCB = new wxComboBox( itemDialog1, ID_DBASECOMBOBOX, wxEmptyString, wxDefaultPosition, wxSize(itemDialog1->ConvertDialogToPixels(wxSize(140, -1)).x, -1), m_filenameCBStrings, wxCB_DROPDOWN );
  itemBoxSizer9->Add(m_filenameCB, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 0);

  wxButton* itemButton11 = new wxButton( itemDialog1, ID_ELLIPSIS, _("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
  itemBoxSizer9->Add(itemButton11, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxStaticText* itemStaticText12 = new wxStaticText( itemDialog1, wxID_STATIC, _("Safe Combination:"), wxDefaultPosition, wxDefaultSize, 0 );
  itemBoxSizer4->Add(itemStaticText12, 0, wxALIGN_LEFT|wxALL, 3);

  CSafeCombinationCtrl* combinationEntry = new CSafeCombinationCtrl(itemDialog1, ID_COMBINATION);
  itemBoxSizer4->Add(combinationEntry, 0, wxGROW|wxRIGHT|wxTOP|wxBOTTOM, 5);

  wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
  itemBoxSizer4->Add(itemBoxSizer14, 0, wxGROW|wxALL, 5);

  wxCheckBox* itemCheckBox15 = new wxCheckBox( itemDialog1, ID_READONLY, _("Open as read-only"), wxDefaultPosition, wxDefaultSize, 0 );
  itemCheckBox15->SetValue(false);
  itemBoxSizer14->Add(itemCheckBox15, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);

  itemBoxSizer14->Add(120, 10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxButton* itemButton17 = new wxButton( itemDialog1, ID_NEWDB, _("New\nDatabase"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
  itemBoxSizer14->Add(itemButton17, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP|wxBOTTOM, 5);

  wxStdDialogButtonSizer* itemStdDialogButtonSizer18 = new wxStdDialogButtonSizer;

  itemBoxSizer4->Add(itemStdDialogButtonSizer18, 0, wxGROW|wxALL, 0);
  wxButton* itemButton19 = new wxButton( itemDialog1, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
  itemButton19->SetDefault();
  itemStdDialogButtonSizer18->AddButton(itemButton19);

  wxButton* itemButton20 = new wxButton( itemDialog1, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
  itemStdDialogButtonSizer18->AddButton(itemButton20);

  wxButton* itemButton21 = new wxButton( itemDialog1, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, 0 );
  itemStdDialogButtonSizer18->AddButton(itemButton21);

  itemStdDialogButtonSizer18->Realize();

  // Set validators
  m_filenameCB->SetValidator( wxGenericValidator(& m_filename) );
  combinationEntry->textCtrl->SetValidator( wxGenericValidator(& m_password) );
  itemCheckBox15->SetValidator( wxGenericValidator(& m_readOnly) );
////@end CSafeCombinationEntry content construction
#if (REVISION == 0)
  m_version->SetLabel(wxString::Format(_("V%d.%02d %s"),
                                       MAJORVERSION, MINORVERSION, SPECIALBUILD));
#else
  m_version->SetLabel(wxString::Format(_("V%d.%02d.%d %s"),
                                       MAJORVERSION, MINORVERSION,
                                       REVISION, SPECIALBUILD));
#endif
  wxArrayString recentFiles;
  wxGetApp().recentDatabases().GetAll(recentFiles);
  m_filenameCB->Append(recentFiles);
  // if m_readOnly, then don't allow user to change it
  itemCheckBox15->Enable(!m_readOnly);
  // if filename field not empty, set focus to password:
  if (!m_filename.empty()) {
    FindWindow(ID_COMBINATION)->SetFocus();
  }
}

/*!
 * Should we show tooltips?
 */

bool CSafeCombinationEntry::ShowToolTips()
{
  return true;
}

/*!
 * Get bitmap resources
 */

wxBitmap CSafeCombinationEntry::GetBitmapResource( const wxString& name )
{
  // Bitmap retrieval
////@begin CSafeCombinationEntry bitmap retrieval
  wxUnusedVar(name);
  if (name == _T("../graphics/wxWidgets/cpane.xpm"))
  {
    wxBitmap bitmap(cpane_xpm);
    return bitmap;
  }
  else if (name == _T("../graphics/wxWidgets/psafetxt.xpm"))
  {
    wxBitmap bitmap(psafetxt_xpm);
    return bitmap;
  }
  return wxNullBitmap;
////@end CSafeCombinationEntry bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon CSafeCombinationEntry::GetIconResource( const wxString& name )
{
  // Icon retrieval
////@begin CSafeCombinationEntry icon retrieval
  wxUnusedVar(name);
  return wxNullIcon;
////@end CSafeCombinationEntry icon retrieval
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK
 */

void CSafeCombinationEntry::OnOk( wxCommandEvent& )
{
  if (Validate() && TransferDataFromWindow()) {
    if (m_password.empty()) {
      wxMessageDialog err(this, _("The combination cannot be blank."),
                          _("Error"), wxOK | wxICON_EXCLAMATION);
      err.ShowModal();
      return;
    }
    if (!pws_os::FileExists(m_filename.c_str())) {
      wxMessageDialog err(this, _("File or path not found."),
                          _("Error"), wxOK | wxICON_EXCLAMATION);
      err.ShowModal();
      return;
    }
    int status = m_core.CheckPasskey(m_filename.c_str(), m_password.c_str());
    wxString errmess;
    switch (status) {
    case PWScore::SUCCESS:
      m_core.SetReadOnly(m_readOnly);
      m_core.SetCurFile(m_filename.c_str());
      wxGetApp().recentDatabases().AddFileToHistory(m_filename);
      EndModal(wxID_OK);
      return;
    case PWScore::CANT_OPEN_FILE:
      { stringT str;
        LoadAString(str, IDSC_FILE_UNREADABLE);
        errmess = str.c_str();
      }
      break;
    case PWScore::WRONG_PASSWORD:
    default:
      if (m_tries >= 2) {
        errmess = _("Three strikes - yer out!");
      } else {
        m_tries++;
        errmess = _("Incorrect passkey, not a PasswordSafe database, or a corrupt database. (Backup database has same name as original, ending with '~')");
      }
      break;
    } // switch (status)
    // here iff CheckPasskey failed.
    wxMessageDialog err(this, errmess,
                        _("Error"), wxOK | wxICON_EXCLAMATION);
    err.ShowModal();
    wxTextCtrl *txt = (wxTextCtrl *)FindWindow(ID_COMBINATION);
    txt->SetSelection(-1,-1);
    txt->SetFocus();
  } // Validate && TransferDataFromWindow
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
 */

void CSafeCombinationEntry::OnCancel( wxCommandEvent& event )
{
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in CSafeCombinationEntry.
  // Before editing this code, remove the block markers.
  event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in CSafeCombinationEntry.
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_ELLIPSIS
 */

void CSafeCombinationEntry::OnEllipsisClick( wxCommandEvent& /* evt */ )
{
  wxFileDialog fd(this, _("Please Choose a Database to Open:"),
                  wxT(""), wxT(""),
                  _("Password Safe Databases (*.psafe3; *.dat)|*.psafe3;*.dat| All files (*.*; *)|*.*;*"),
                  (wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR));

  if (fd.ShowModal() == wxID_OK) {
    m_filename = fd.GetPath();
    wxComboBox *cb = (wxComboBox *)FindWindow(ID_DBASECOMBOBOX);
    cb->SetValue(m_filename);
  }
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_NEWDB
 */

void CSafeCombinationEntry::OnNewDbClick( wxCommandEvent& /* evt */ )
{
  // 1. Get a filename from a file dialog box
  // 2. Get a password
  // 3. Set m_filespec && m_passkey to returned value!
  wxString newfile;
  wxString cs_msg, cs_title, cs_temp;

  wxString cf(_("pwsafe")); // reasonable default for first time user
  stringT v3FileName = PWSUtil::GetNewFileName(cf.c_str(), _("psafe3"));
  stringT dir = PWSdirs::GetSafeDir();

  while (1) {
    wxFileDialog fd(this, _("Please choose a name for the new database"),
                    dir.c_str(), v3FileName.c_str(),
                    _("Password Safe Databases (*.psafe3; *.dat)|*.psafe3;*.dat| All files (*.*; *)|*.*;*"),
                  (wxFD_SAVE | wxFD_OVERWRITE_PROMPT| wxFD_CHANGE_DIR));
    int rc = fd.ShowModal();
    if (rc == wxID_OK) {
      newfile = fd.GetPath();
      break;
    } else
      return;
  }
  // 2. Get a password
  CSafeCombinationSetup pksetup(this);
  int rc = pksetup.ShowModal();

  if (rc != wxID_OK)
    return;  //User cancelled password entry

  // 3. Set m_filespec && m_passkey to returned value!
  m_core.SetCurFile(newfile.c_str());
  m_core.SetPassKey(pksetup.GetPassword().c_str());
  wxGetApp().recentDatabases().AddFileToHistory(newfile);
  EndModal(wxID_OK);
}

<commit_msg>Use CreateStdDialogButtonSizer instead of manually adding buttons to wxStdDialogButtonSizer<commit_after>/*
 * Copyright (c) 2003-2010 Rony Shapiro <ronys@users.sourceforge.net>.
 * All rights reserved. Use of the code is allowed under the
 * Artistic License 2.0 terms, as specified in the LICENSE file
 * distributed with this code, or available from
 * http://www.opensource.org/licenses/artistic-license-2.0.php
 */

/** \file safecombinationentry.cpp
*
*/
// Generated by DialogBlocks, Sun 18 Jan 2009 09:22:13 PM IST

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

////@begin includes
////@end includes

#include "safecombinationentry.h"
#include "safecombinationsetup.h"
#include "version.h"
#include "corelib/corelib.h"
#include "corelib/PWSdirs.h"
#include "os/file.h"
////@begin XPM images
#include "../graphics/wxWidgets/cpane.xpm"
#include "../graphics/wxWidgets/psafetxt.xpm"
////@end XPM images
#include "pwsafeapp.h"
#include "SafeCombinationCtrl.h"

/*!
 * CSafeCombinationEntry type definition
 */

IMPLEMENT_CLASS( CSafeCombinationEntry, wxDialog )

/*!
 * CSafeCombinationEntry event table definition
 */

BEGIN_EVENT_TABLE( CSafeCombinationEntry, wxDialog )

////@begin CSafeCombinationEntry event table entries
  EVT_BUTTON( ID_ELLIPSIS, CSafeCombinationEntry::OnEllipsisClick )

  EVT_BUTTON( ID_NEWDB, CSafeCombinationEntry::OnNewDbClick )

  EVT_BUTTON( wxID_OK, CSafeCombinationEntry::OnOk )

  EVT_BUTTON( wxID_CANCEL, CSafeCombinationEntry::OnCancel )
////@end CSafeCombinationEntry event table entries

END_EVENT_TABLE()

/*!
 * CSafeCombinationEntry constructors
 */

CSafeCombinationEntry::CSafeCombinationEntry(PWScore &core)
: m_core(core), m_tries(0)
{
  Init();
}

CSafeCombinationEntry::CSafeCombinationEntry(wxWindow* parent, PWScore &core,
                                             wxWindowID id,
                                             const wxString& caption,
                                             const wxPoint& pos,
                                             const wxSize& size, long style)
  : m_core(core), m_tries(0)
{
  Init();
  Create(parent, id, caption, pos, size, style);
}

/*!
 * CSafeCombinationEntry creator
 */

bool CSafeCombinationEntry::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin CSafeCombinationEntry creation
  SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
  wxDialog::Create( parent, id, caption, pos, size, style );

  CreateControls();
  if (GetSizer())
  {
    GetSizer()->SetSizeHints(this);
  }
  Centre();
////@end CSafeCombinationEntry creation
  return true;
}

/*!
 * CSafeCombinationEntry destructor
 */

CSafeCombinationEntry::~CSafeCombinationEntry()
{
////@begin CSafeCombinationEntry destruction
////@end CSafeCombinationEntry destruction
}

/*!
 * Member initialisation
 */

void CSafeCombinationEntry::Init()
{
  m_readOnly = m_core.IsReadOnly();
  m_filename = m_core.GetCurFile().c_str();
////@begin CSafeCombinationEntry member initialisation
  m_version = NULL;
  m_filenameCB = NULL;
////@end CSafeCombinationEntry member initialisation
}

/*!
 * Control creation for CSafeCombinationEntry
 */

void CSafeCombinationEntry::CreateControls()
{
////@begin CSafeCombinationEntry content construction
  CSafeCombinationEntry* itemDialog1 = this;

  wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
  itemDialog1->SetSizer(itemBoxSizer2);

  wxStaticBitmap* itemStaticBitmap3 = new wxStaticBitmap( itemDialog1, wxID_STATIC, itemDialog1->GetBitmapResource(wxT("../graphics/wxWidgets/cpane.xpm")), wxDefaultPosition, itemDialog1->ConvertDialogToPixels(wxSize(49, 46)), 0 );
  itemBoxSizer2->Add(itemStaticBitmap3, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxVERTICAL);
  itemBoxSizer2->Add(itemBoxSizer4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
  itemBoxSizer4->Add(itemBoxSizer5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);

  wxStaticBitmap* itemStaticBitmap6 = new wxStaticBitmap( itemDialog1, wxID_STATIC, itemDialog1->GetBitmapResource(wxT("../graphics/wxWidgets/psafetxt.xpm")), wxDefaultPosition, itemDialog1->ConvertDialogToPixels(wxSize(111, 16)), 0 );
  itemBoxSizer5->Add(itemStaticBitmap6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  m_version = new wxStaticText( itemDialog1, wxID_STATIC, _("VX.YY"), wxDefaultPosition, wxDefaultSize, 0 );
  itemBoxSizer5->Add(m_version, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxStaticText* itemStaticText8 = new wxStaticText( itemDialog1, wxID_STATIC, _("Open Password Database:"), wxDefaultPosition, wxDefaultSize, 0 );
  itemBoxSizer4->Add(itemStaticText8, 0, wxALIGN_LEFT|wxALL, 3);

  wxBoxSizer* itemBoxSizer9 = new wxBoxSizer(wxHORIZONTAL);
  itemBoxSizer4->Add(itemBoxSizer9, 50, wxGROW|wxALL, 5);

  wxArrayString m_filenameCBStrings;
  m_filenameCB = new wxComboBox( itemDialog1, ID_DBASECOMBOBOX, wxEmptyString, wxDefaultPosition, wxSize(itemDialog1->ConvertDialogToPixels(wxSize(140, -1)).x, -1), m_filenameCBStrings, wxCB_DROPDOWN );
  itemBoxSizer9->Add(m_filenameCB, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 0);

  wxButton* itemButton11 = new wxButton( itemDialog1, ID_ELLIPSIS, _("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
  itemBoxSizer9->Add(itemButton11, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxStaticText* itemStaticText12 = new wxStaticText( itemDialog1, wxID_STATIC, _("Safe Combination:"), wxDefaultPosition, wxDefaultSize, 0 );
  itemBoxSizer4->Add(itemStaticText12, 0, wxALIGN_LEFT|wxALL, 3);

  CSafeCombinationCtrl* combinationEntry = new CSafeCombinationCtrl(itemDialog1, ID_COMBINATION);
  itemBoxSizer4->Add(combinationEntry, 0, wxGROW|wxRIGHT|wxTOP|wxBOTTOM, 5);

  wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
  itemBoxSizer4->Add(itemBoxSizer14, 0, wxGROW|wxALL, 5);

  wxCheckBox* itemCheckBox15 = new wxCheckBox( itemDialog1, ID_READONLY, _("Open as read-only"), wxDefaultPosition, wxDefaultSize, 0 );
  itemCheckBox15->SetValue(false);
  itemBoxSizer14->Add(itemCheckBox15, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);

  itemBoxSizer14->Add(120, 10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

  wxButton* itemButton17 = new wxButton( itemDialog1, ID_NEWDB, _("New\nDatabase"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
  itemBoxSizer14->Add(itemButton17, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP|wxBOTTOM, 5);

  itemBoxSizer4->Add(CreateStdDialogButtonSizer(wxOK|wxCANCEL|wxHELP), 0, wxGROW|wxALL, 0);

  // Set validators
  m_filenameCB->SetValidator( wxGenericValidator(& m_filename) );
  combinationEntry->textCtrl->SetValidator( wxGenericValidator(& m_password) );
  itemCheckBox15->SetValidator( wxGenericValidator(& m_readOnly) );
////@end CSafeCombinationEntry content construction
#if (REVISION == 0)
  m_version->SetLabel(wxString::Format(_("V%d.%02d %s"),
                                       MAJORVERSION, MINORVERSION, SPECIALBUILD));
#else
  m_version->SetLabel(wxString::Format(_("V%d.%02d.%d %s"),
                                       MAJORVERSION, MINORVERSION,
                                       REVISION, SPECIALBUILD));
#endif
  wxArrayString recentFiles;
  wxGetApp().recentDatabases().GetAll(recentFiles);
  m_filenameCB->Append(recentFiles);
  // if m_readOnly, then don't allow user to change it
  itemCheckBox15->Enable(!m_readOnly);
  // if filename field not empty, set focus to password:
  if (!m_filename.empty()) {
    FindWindow(ID_COMBINATION)->SetFocus();
  }
}

/*!
 * Should we show tooltips?
 */

bool CSafeCombinationEntry::ShowToolTips()
{
  return true;
}

/*!
 * Get bitmap resources
 */

wxBitmap CSafeCombinationEntry::GetBitmapResource( const wxString& name )
{
  // Bitmap retrieval
////@begin CSafeCombinationEntry bitmap retrieval
  wxUnusedVar(name);
  if (name == _T("../graphics/wxWidgets/cpane.xpm"))
  {
    wxBitmap bitmap(cpane_xpm);
    return bitmap;
  }
  else if (name == _T("../graphics/wxWidgets/psafetxt.xpm"))
  {
    wxBitmap bitmap(psafetxt_xpm);
    return bitmap;
  }
  return wxNullBitmap;
////@end CSafeCombinationEntry bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon CSafeCombinationEntry::GetIconResource( const wxString& name )
{
  // Icon retrieval
////@begin CSafeCombinationEntry icon retrieval
  wxUnusedVar(name);
  return wxNullIcon;
////@end CSafeCombinationEntry icon retrieval
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK
 */

void CSafeCombinationEntry::OnOk( wxCommandEvent& )
{
  if (Validate() && TransferDataFromWindow()) {
    if (m_password.empty()) {
      wxMessageDialog err(this, _("The combination cannot be blank."),
                          _("Error"), wxOK | wxICON_EXCLAMATION);
      err.ShowModal();
      return;
    }
    if (!pws_os::FileExists(m_filename.c_str())) {
      wxMessageDialog err(this, _("File or path not found."),
                          _("Error"), wxOK | wxICON_EXCLAMATION);
      err.ShowModal();
      return;
    }
    int status = m_core.CheckPasskey(m_filename.c_str(), m_password.c_str());
    wxString errmess;
    switch (status) {
    case PWScore::SUCCESS:
      m_core.SetReadOnly(m_readOnly);
      m_core.SetCurFile(m_filename.c_str());
      wxGetApp().recentDatabases().AddFileToHistory(m_filename);
      EndModal(wxID_OK);
      return;
    case PWScore::CANT_OPEN_FILE:
      { stringT str;
        LoadAString(str, IDSC_FILE_UNREADABLE);
        errmess = str.c_str();
      }
      break;
    case PWScore::WRONG_PASSWORD:
    default:
      if (m_tries >= 2) {
        errmess = _("Three strikes - yer out!");
      } else {
        m_tries++;
        errmess = _("Incorrect passkey, not a PasswordSafe database, or a corrupt database. (Backup database has same name as original, ending with '~')");
      }
      break;
    } // switch (status)
    // here iff CheckPasskey failed.
    wxMessageDialog err(this, errmess,
                        _("Error"), wxOK | wxICON_EXCLAMATION);
    err.ShowModal();
    wxTextCtrl *txt = (wxTextCtrl *)FindWindow(ID_COMBINATION);
    txt->SetSelection(-1,-1);
    txt->SetFocus();
  } // Validate && TransferDataFromWindow
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
 */

void CSafeCombinationEntry::OnCancel( wxCommandEvent& event )
{
////@begin wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in CSafeCombinationEntry.
  // Before editing this code, remove the block markers.
  event.Skip();
////@end wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL in CSafeCombinationEntry.
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_ELLIPSIS
 */

void CSafeCombinationEntry::OnEllipsisClick( wxCommandEvent& /* evt */ )
{
  wxFileDialog fd(this, _("Please Choose a Database to Open:"),
                  wxT(""), wxT(""),
                  _("Password Safe Databases (*.psafe3; *.dat)|*.psafe3;*.dat| All files (*.*; *)|*.*;*"),
                  (wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR));

  if (fd.ShowModal() == wxID_OK) {
    m_filename = fd.GetPath();
    wxComboBox *cb = (wxComboBox *)FindWindow(ID_DBASECOMBOBOX);
    cb->SetValue(m_filename);
  }
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_NEWDB
 */

void CSafeCombinationEntry::OnNewDbClick( wxCommandEvent& /* evt */ )
{
  // 1. Get a filename from a file dialog box
  // 2. Get a password
  // 3. Set m_filespec && m_passkey to returned value!
  wxString newfile;
  wxString cs_msg, cs_title, cs_temp;

  wxString cf(_("pwsafe")); // reasonable default for first time user
  stringT v3FileName = PWSUtil::GetNewFileName(cf.c_str(), _("psafe3"));
  stringT dir = PWSdirs::GetSafeDir();

  while (1) {
    wxFileDialog fd(this, _("Please choose a name for the new database"),
                    dir.c_str(), v3FileName.c_str(),
                    _("Password Safe Databases (*.psafe3; *.dat)|*.psafe3;*.dat| All files (*.*; *)|*.*;*"),
                  (wxFD_SAVE | wxFD_OVERWRITE_PROMPT| wxFD_CHANGE_DIR));
    int rc = fd.ShowModal();
    if (rc == wxID_OK) {
      newfile = fd.GetPath();
      break;
    } else
      return;
  }
  // 2. Get a password
  CSafeCombinationSetup pksetup(this);
  int rc = pksetup.ShowModal();

  if (rc != wxID_OK)
    return;  //User cancelled password entry

  // 3. Set m_filespec && m_passkey to returned value!
  m_core.SetCurFile(newfile.c_str());
  m_core.SetPassKey(pksetup.GetPassword().c_str());
  wxGetApp().recentDatabases().AddFileToHistory(newfile);
  EndModal(wxID_OK);
}

<|endoftext|>


<commit_before>#ifndef __GLOBALS_HPP_INCLUDED
#define __GLOBALS_HPP_INCLUDED

#include <string>
#include <vector>
#include <stdint.h> // uint32_t etc.

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#ifndef WINDOW_WIDTH
#define WINDOW_WIDTH (1600.0f)
#endif

#ifndef WINDOW_HEIGHT
#define WINDOW_HEIGHT (900.0f)
#endif

#ifndef ASPECT_RATIO
#define ASPECT_RATIO (WINDOW_WIDTH / WINDOW_HEIGHT)
#endif

#ifndef PI
#define PI 3.14159265359f
#endif

#ifndef EARTH_RADIUS
#define EARTH_RADIUS 6371000.0f
#endif

#ifndef TEXT_SIZE
#define TEXT_SIZE 40
#endif

#ifndef FONT_SIZE
#define FONT_SIZE 16
#endif

#ifndef MAX_FPS
#define MAX_FPS 60
#endif

extern glm::vec3 position;
extern GLfloat gravity;
extern bool inFlightmode;
extern GLfloat fallSpeed;
extern double horizontalAngle;
extern double verticalAngle;
extern GLfloat initialFoV;
extern double earth_radius;
extern bool hasMouseEverMoved;
extern bool is_invert_mouse_in_use;
extern bool is_key_I_released;
extern bool is_world_loaded; // no more than one world object can be loaded. TODO: check that no more than one world is loaded!
extern bool is_world_spherical;

typedef struct
{
    void *world_pointer = NULL;              // pointer to the world (draw list).
    std::string vertex_shader;               // filename of vertex shader.
    std::string fragment_shader;             // filename of fragment shader.
} ShaderStruct;

typedef struct
{
    void *shader_pointer = NULL;             // pointer to the shader.
    std::string texture_file_format;         // type of the texture file. supported file formats so far: `"bmp"`/`"BMP"`, `"dds"`/`"DDS"`.
    std::string texture_filename;            // filename of the model file.
    std::string image_path;
} TextureStruct;

typedef struct
{
    GLuint nodeID;
    void *graph_pointer = NULL;
    glm::vec3 coordinate_vector;
    std::vector<uint32_t> neighbor_nodeIDs;
} NodeStruct;

typedef struct
{
    glm::vec3 coordinate_vector;     // coordinate vector.
    GLfloat rotate_angle = NAN;      // rotate angle.
    glm::vec3 rotate_vector;         // rotate vector.
    glm::vec3 translate_vector;      // translate vector.
    glm::mat4 model_matrix;          // model matrix.
    glm::mat4 MVP_matrix;            // model view projection matrix.
    void *species_pointer = NULL;    // pointer to the species.
} ObjectStruct;

typedef struct
{
    // used for all files (for all species).
    void *texture_pointer = NULL;            // pointer to the texture object.
    std::string model_file_format;           // type of the model file. supported file formats so far: `"bmp"`/`"BMP"`, `"obj"`/`"OBJ"`.
                                             // TODO: add support for `"SRTM"`.
    std::string vertex_shader;               // filename of vertex shader.
    std::string fragment_shader;             // filename of fragment shader.
    glm::vec3 lightPos;                      // light position.
    std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
    bool is_world;                           // worlds currently do not rotate nor translate.
    std::string coordinate_system;           // used only for worlds (`is_world` == `true`). valid values: `"cartesian"`.
                                             // TODO: add support for `"spherical"`. `"spherical"` is used eg. in SRTM heightmaps.
    double world_radius;                    // radius of sea level in meters. used only for worlds.

    // for `"bmp"` model files.
    std::string model_filename;              // filename of the model file.
    std::string color_channel;               // color channel to use for altitude data.
} SpeciesStruct;

typedef struct
{
    GLuint screen_width;
    GLuint screen_height;
    GLuint x;
    GLuint y;
    GLuint text_size;
    GLuint font_size;
    const char *text;
    const char *char_font_texture_file_format;
    const char *horizontal_alignment;
    const char *vertical_alignment;
} PrintingStruct;

typedef struct
{
    double rho;
    double theta;
    double phi;
} SphericalCoordinatesStruct;

typedef struct
{
    double southern_latitude;
    double northern_latitude;
    double western_longitude;
    double eastern_longitude;
} SphericalWorldStruct;

extern SphericalCoordinatesStruct spherical_position;

#endif
<commit_msg>`typedef struct {` ... `} SpeciesStruct`: Muuttuja `is_world`.<commit_after>#ifndef __GLOBALS_HPP_INCLUDED
#define __GLOBALS_HPP_INCLUDED

#include <string>
#include <vector>
#include <stdint.h> // uint32_t etc.

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#ifndef WINDOW_WIDTH
#define WINDOW_WIDTH (1600.0f)
#endif

#ifndef WINDOW_HEIGHT
#define WINDOW_HEIGHT (900.0f)
#endif

#ifndef ASPECT_RATIO
#define ASPECT_RATIO (WINDOW_WIDTH / WINDOW_HEIGHT)
#endif

#ifndef PI
#define PI 3.14159265359f
#endif

#ifndef EARTH_RADIUS
#define EARTH_RADIUS 6371000.0f
#endif

#ifndef TEXT_SIZE
#define TEXT_SIZE 40
#endif

#ifndef FONT_SIZE
#define FONT_SIZE 16
#endif

#ifndef MAX_FPS
#define MAX_FPS 60
#endif

extern glm::vec3 position;
extern GLfloat gravity;
extern bool inFlightmode;
extern GLfloat fallSpeed;
extern double horizontalAngle;
extern double verticalAngle;
extern GLfloat initialFoV;
extern double earth_radius;
extern bool hasMouseEverMoved;
extern bool is_invert_mouse_in_use;
extern bool is_key_I_released;
extern bool is_world_loaded; // no more than one world object can be loaded. TODO: check that no more than one world is loaded!
extern bool is_world_spherical;

typedef struct
{
    void *world_pointer = NULL;              // pointer to the world (draw list).
    std::string vertex_shader;               // filename of vertex shader.
    std::string fragment_shader;             // filename of fragment shader.
} ShaderStruct;

typedef struct
{
    void *shader_pointer = NULL;             // pointer to the shader.
    std::string texture_file_format;         // type of the texture file. supported file formats so far: `"bmp"`/`"BMP"`, `"dds"`/`"DDS"`.
    std::string texture_filename;            // filename of the model file.
    std::string image_path;
} TextureStruct;

typedef struct
{
    GLuint nodeID;
    void *graph_pointer = NULL;
    glm::vec3 coordinate_vector;
    std::vector<uint32_t> neighbor_nodeIDs;
} NodeStruct;

typedef struct
{
    glm::vec3 coordinate_vector;     // coordinate vector.
    GLfloat rotate_angle = NAN;      // rotate angle.
    glm::vec3 rotate_vector;         // rotate vector.
    glm::vec3 translate_vector;      // translate vector.
    glm::mat4 model_matrix;          // model matrix.
    glm::mat4 MVP_matrix;            // model view projection matrix.
    void *species_pointer = NULL;    // pointer to the species.
} ObjectStruct;

typedef struct
{
    // used for all files (for all species).
    void *texture_pointer = NULL;            // pointer to the texture object.
    std::string model_file_format;           // type of the model file. supported file formats so far: `"bmp"`/`"BMP"`, `"obj"`/`"OBJ"`.
                                             // TODO: add support for `"SRTM"`.
    std::string vertex_shader;               // filename of vertex shader.
    std::string fragment_shader;             // filename of fragment shader.
    glm::vec3 lightPos;                      // light position.
    std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
    bool is_world = false;                   // worlds currently do not rotate nor translate.
    std::string coordinate_system;           // used only for worlds (`is_world` == `true`). valid values: `"cartesian"`.
                                             // TODO: add support for `"spherical"`. `"spherical"` is used eg. in SRTM heightmaps.
    double world_radius;                    // radius of sea level in meters. used only for worlds.

    // for `"bmp"` model files.
    std::string model_filename;              // filename of the model file.
    std::string color_channel;               // color channel to use for altitude data.
} SpeciesStruct;

typedef struct
{
    GLuint screen_width;
    GLuint screen_height;
    GLuint x;
    GLuint y;
    GLuint text_size;
    GLuint font_size;
    const char *text;
    const char *char_font_texture_file_format;
    const char *horizontal_alignment;
    const char *vertical_alignment;
} PrintingStruct;

typedef struct
{
    double rho;
    double theta;
    double phi;
} SphericalCoordinatesStruct;

typedef struct
{
    double southern_latitude;
    double northern_latitude;
    double western_longitude;
    double eastern_longitude;
} SphericalWorldStruct;

extern SphericalCoordinatesStruct spherical_position;

#endif
<|endoftext|>


<commit_before>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2015 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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.

******************************************************************************/

#include "nwchemjson.h"

#include <avogadro/core/crystaltools.h>
#include <avogadro/core/elements.h>
#include <avogadro/core/gaussianset.h>
#include <avogadro/core/molecule.h>
#include <avogadro/core/unitcell.h>
#include <avogadro/core/utilities.h>

#include <jsoncpp.cpp>

#include <iostream>

namespace Avogadro {
namespace QuantumIO {

using std::string;
using std::vector;
using std::cout;
using std::endl;

using Json::Value;
using Json::Reader;
using Json::StyledStreamWriter;

using Core::Array;
using Core::Atom;
using Core::BasisSet;
using Core::Bond;
using Core::CrystalTools;
using Core::Elements;
using Core::GaussianSet;
using Core::Molecule;
using Core::Variant;
using Core::split;

NWChemJson::NWChemJson()
{
}

NWChemJson::~NWChemJson()
{
}

bool NWChemJson::read(std::istream &file, Molecule &molecule)
{
  Value root;
  Reader reader;
  bool ok = reader.parse(file, root);
  if (!ok) {
    appendError("Error parsing JSON: " + reader.getFormatedErrorMessages());
    return false;
  }

  if (!root.isObject()) {
    appendError("Error: Input is not a JSON object.");
    return false;
  }

  Value simulation = root["simulation"];
  if (simulation.empty()) {
    appendError("Error: no \"simulation\" key found.");
    return false;
  }

  // Scan the calculations array for calculationSetup.molecule objects.
  Value calculations = simulation["calculations"];
  if (calculations.empty() || !calculations.isArray()) {
    appendError("Error: no \"calculations\" array found.");
    return false;
  }

  // Iterate through the objects in the array, and print out any molecules.
  Value moleculeArray(Json::arrayValue);
  Value basisSetArray(Json::arrayValue);
  Value calculationVib;
  Value molecularOrbitals;
  int numberOfElectrons = 0;
  for (size_t i = 0; i < calculations.size(); ++i) {
    Value calcObj = calculations.get(i, "");
    if (calcObj.isObject()) {
      string calcType = calcObj["calculationType"].asString();
      // Store the last vibrational frequencies calculation object.
      if (calcType == "vibrationalModes")
        calculationVib = calcObj;
      Value calcSetup = calcObj["calculationSetup"];
      Value calcMol = calcSetup["molecule"];
      numberOfElectrons = calcSetup["numberOfElectrons"].asInt();
      if (!calcMol.isNull() && calcMol.isObject())
        moleculeArray.append(calcMol);
      Value basisSet = calcSetup["basisSet"];
      if (!basisSet.isNull() && basisSet.isObject())
        basisSetArray.append(basisSet);

      Value calcResults = calcObj["calculationResults"];
      calcMol = calcResults["molecule"];
      if (!calcMol.isNull() && calcMol.isObject())
        moleculeArray.append(calcMol);
      // There is currently one id for all, just get the last one we find.
      if (!calcResults["molecularOrbitals"].isNull()
          && calcResults["molecularOrbitals"].isObject())
        molecularOrbitals = calcResults["molecularOrbitals"];
    }
  }

  // For now, we are just grabbing the "last" molecule, and using that. This
  // needs more complex logic to step through the file and do it properly.
  Value finalMol = moleculeArray.get(moleculeArray.size() - 1, 0);
  Value atoms = finalMol["atoms"];
  if (atoms.isArray()) {
    for (size_t i = 0; i < atoms.size(); ++i) {
      Value jsonAtom = atoms.get(i, 0);
      if (jsonAtom.isNull() || !jsonAtom.isObject())
        continue;
      Atom a =
          molecule.addAtom(static_cast<unsigned char>(jsonAtom["elementNumber"]
                           .asInt()));
      Value pos = jsonAtom["cartesianCoordinates"]["value"];
      Vector3 position(pos.get(Json::Value::ArrayIndex(0), 0.0).asDouble(),
                       pos.get(Json::Value::ArrayIndex(1), 0.0).asDouble(),
                       pos.get(Json::Value::ArrayIndex(2), 0.0).asDouble());
      string units = jsonAtom["cartesianCoordinates"]["units"].asString();
      if (units == "bohr")
        position *= BOHR_TO_ANGSTROM_D;
      a.setPosition3d(position);
    }
  }
  // Perceive bonds for the molecule.
  molecule.perceiveBondsSimple();

  // Add in the electronic structure information if available.
  if (molecularOrbitals.isObject()
      && molecularOrbitals["atomicOrbitalDescriptions"].isArray()) {
    Value basisSet = basisSetArray.get(basisSetArray.size() - 1, 0);
    Value orbDesc = molecularOrbitals["atomicOrbitalDescriptions"];

    // Figure out the mapping of basis set to molecular orbitals.
    Array<int> atomNumber;
    Array<string> atomSymbol;
    for (size_t i = 0; i < orbDesc.size(); ++i) {
      string desc = orbDesc.get(i, 0).asString();
      vector<string> parts = split(desc, ' ');
      assert(parts.size() == 3);
      int num = Core::lexicalCast<int>(parts[0]);
      if (atomNumber.size() > 0 && atomNumber.back() == num)
        continue;
      atomNumber.push_back(num);
      atomSymbol.push_back(parts[1]);
    }

    // Now create the structure, and expand out the orbitals.
    GaussianSet *basis = new GaussianSet;
    basis->setMolecule(&molecule);
    for (size_t i = 0; i < atomSymbol.size(); ++i) {
      string symbol = atomSymbol[i];
      Value basisFunctions = basisSet["basisFunctions"];
      Value currentFunction;
      for (size_t j = 0; j < basisFunctions.size(); ++j) {
        currentFunction = basisFunctions.get(j, 0);

        string elementType;
        if (currentFunction.isMember("elementLabel"))
          elementType = currentFunction["elementLabel"].asString();
        else if (currentFunction.isMember("elementType"))
          elementType = currentFunction["elementType"].asString();

        if (elementType == symbol)
          break;

        currentFunction = Json::nullValue;
      }

      if (currentFunction.isNull())
        break;

      Value contraction = currentFunction["basisSetContraction"];
      bool spherical = currentFunction["basisSetHarmonicType"].asString()
          == "spherical";
      for (size_t j = 0; j < contraction.size(); ++j) {
        Value contractionShell = contraction.get(j, Json::nullValue);
        string shellType;
        if (contractionShell.isMember("basisSetShell"))
          shellType = contractionShell["basisSetShell"].asString();
        else if (contractionShell.isMember("basisSetShellType"))
          shellType = contractionShell["basisSetShellType"].asString();
        Value exponent = contractionShell["basisSetExponent"];
        Value coefficient = contractionShell["basisSetCoefficient"];
        assert(exponent.size() == coefficient.size());
        GaussianSet::orbital type = GaussianSet::UU;
        if (shellType == "s")
          type = GaussianSet::S;
        else if (shellType == "p")
          type = GaussianSet::P;
        else if (shellType == "d" && spherical)
          type = GaussianSet::D5;
        else if (shellType == "d")
          type = GaussianSet::D;
        else if (shellType == "f" && spherical)
          type = GaussianSet::F7;
        else if (shellType == "f")
          type == GaussianSet::F;

        if (type != GaussianSet::UU) {
          int b = basis->addBasis(i, type);
          for (size_t k = 0; k < exponent.size(); ++k) {
            basis->addGto(b, coefficient.get(k, 0).asDouble(),
                          exponent.get(k, 0).asDouble());
          }
        }
      }
    }
    // Now to add the molecular orbital coefficients.
    Value moCoeffs = molecularOrbitals["molecularOrbital"];
    vector<double> coeffArray;
    for (size_t i = 0; i < moCoeffs.size(); ++i) {
      Value coeff = moCoeffs.get(i, Json::nullValue)["moCoefficients"];
      for (size_t j = 0; j < coeff.size(); ++j)
        coeffArray.push_back(coeff.get(j, 0).asDouble());
    }
    basis->setMolecularOrbitals(coeffArray);
    basis->setElectronCount(numberOfElectrons);
    molecule.setBasisSet(basis);
  }

  // Now to see if there was a vibrational frequencies calculation.
  if (!calculationVib.isNull() && calculationVib.isObject()) {
    Value normalModes = calculationVib["calculationResults"]["normalModes"];
    if (!normalModes.isNull() && normalModes.isArray()) {
      Array<double> frequencies;
      Array<double> intensities;
      Array< Array<Vector3> > Lx;
      for (size_t i = 0; i < normalModes.size(); ++i) {
        Value mode = normalModes.get(i, "");
        frequencies.push_back(mode["normalModeFrequency"]["value"].asDouble());
        intensities.push_back(mode["normalModeInfraRedIntensity"]["value"].asDouble());
        Value lx = mode["normalModeVector"]["value"];
        if (!lx.empty() && lx.isArray()) {
          Array<Vector3> modeLx;
          modeLx.resize(lx.size() / 3);
          for (size_t k = 0; k < lx.size(); ++k)
            modeLx[k / 3][k % 3] = lx.get(k, 0).asDouble();
          Lx.push_back(modeLx);
        }
      }
      molecule.setVibrationFrequencies(frequencies);
      molecule.setVibrationIntensities(intensities);
      molecule.setVibrationLx(Lx);
    }
  }

  return true;
}

bool NWChemJson::write(std::ostream &file, const Molecule &molecule)
{
  return false;
}

vector<std::string> NWChemJson::fileExtensions() const
{
  vector<std::string> ext;
  ext.push_back("json");
  ext.push_back("nwjson");
  return ext;
}

vector<std::string> NWChemJson::mimeTypes() const
{
  vector<std::string> mime;
  mime.push_back("chemical/x-nwjson");
  return mime;
}

} // end QuantumIO namespace
} // end Avogadro namespace
<commit_msg>Read in additional MO data when available<commit_after>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2015 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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.

******************************************************************************/

#include "nwchemjson.h"

#include <avogadro/core/crystaltools.h>
#include <avogadro/core/elements.h>
#include <avogadro/core/gaussianset.h>
#include <avogadro/core/molecule.h>
#include <avogadro/core/unitcell.h>
#include <avogadro/core/utilities.h>

#include <jsoncpp.cpp>

#include <iostream>

namespace Avogadro {
namespace QuantumIO {

using std::string;
using std::vector;
using std::cout;
using std::endl;

using Json::Value;
using Json::Reader;
using Json::StyledStreamWriter;

using Core::Array;
using Core::Atom;
using Core::BasisSet;
using Core::Bond;
using Core::CrystalTools;
using Core::Elements;
using Core::GaussianSet;
using Core::Molecule;
using Core::Variant;
using Core::split;

NWChemJson::NWChemJson()
{
}

NWChemJson::~NWChemJson()
{
}

bool NWChemJson::read(std::istream &file, Molecule &molecule)
{
  Value root;
  Reader reader;
  bool ok = reader.parse(file, root);
  if (!ok) {
    appendError("Error parsing JSON: " + reader.getFormatedErrorMessages());
    return false;
  }

  if (!root.isObject()) {
    appendError("Error: Input is not a JSON object.");
    return false;
  }

  Value simulation = root["simulation"];
  if (simulation.empty()) {
    appendError("Error: no \"simulation\" key found.");
    return false;
  }

  // Scan the calculations array for calculationSetup.molecule objects.
  Value calculations = simulation["calculations"];
  if (calculations.empty() || !calculations.isArray()) {
    appendError("Error: no \"calculations\" array found.");
    return false;
  }

  // Iterate through the objects in the array, and print out any molecules.
  Value moleculeArray(Json::arrayValue);
  Value basisSetArray(Json::arrayValue);
  Value calculationVib;
  Value molecularOrbitals;
  int numberOfElectrons = 0;
  for (size_t i = 0; i < calculations.size(); ++i) {
    Value calcObj = calculations.get(i, "");
    if (calcObj.isObject()) {
      string calcType = calcObj["calculationType"].asString();
      // Store the last vibrational frequencies calculation object.
      if (calcType == "vibrationalModes")
        calculationVib = calcObj;
      Value calcSetup = calcObj["calculationSetup"];
      Value calcMol = calcSetup["molecule"];
      numberOfElectrons = calcSetup["numberOfElectrons"].asInt();
      if (!calcMol.isNull() && calcMol.isObject())
        moleculeArray.append(calcMol);
      Value basisSet = calcSetup["basisSet"];
      if (!basisSet.isNull() && basisSet.isObject())
        basisSetArray.append(basisSet);

      Value calcResults = calcObj["calculationResults"];
      calcMol = calcResults["molecule"];
      if (!calcMol.isNull() && calcMol.isObject())
        moleculeArray.append(calcMol);
      // There is currently one id for all, just get the last one we find.
      if (!calcResults["molecularOrbitals"].isNull()
          && calcResults["molecularOrbitals"].isObject())
        molecularOrbitals = calcResults["molecularOrbitals"];
    }
  }

  // For now, we are just grabbing the "last" molecule, and using that. This
  // needs more complex logic to step through the file and do it properly.
  Value finalMol = moleculeArray.get(moleculeArray.size() - 1, 0);
  Value atoms = finalMol["atoms"];
  if (atoms.isArray()) {
    for (size_t i = 0; i < atoms.size(); ++i) {
      Value jsonAtom = atoms.get(i, 0);
      if (jsonAtom.isNull() || !jsonAtom.isObject())
        continue;
      Atom a =
          molecule.addAtom(static_cast<unsigned char>(jsonAtom["elementNumber"]
                           .asInt()));
      Value pos = jsonAtom["cartesianCoordinates"]["value"];
      Vector3 position(pos.get(Json::Value::ArrayIndex(0), 0.0).asDouble(),
                       pos.get(Json::Value::ArrayIndex(1), 0.0).asDouble(),
                       pos.get(Json::Value::ArrayIndex(2), 0.0).asDouble());
      string units = jsonAtom["cartesianCoordinates"]["units"].asString();
      if (units == "bohr")
        position *= BOHR_TO_ANGSTROM_D;
      a.setPosition3d(position);
    }
  }
  // Perceive bonds for the molecule.
  molecule.perceiveBondsSimple();

  // Add in the electronic structure information if available.
  if (molecularOrbitals.isObject()
      && molecularOrbitals["atomicOrbitalDescriptions"].isArray()) {
    Value basisSet = basisSetArray.get(basisSetArray.size() - 1, 0);
    Value orbDesc = molecularOrbitals["atomicOrbitalDescriptions"];

    // Figure out the mapping of basis set to molecular orbitals.
    Array<int> atomNumber;
    Array<string> atomSymbol;
    for (size_t i = 0; i < orbDesc.size(); ++i) {
      string desc = orbDesc.get(i, 0).asString();
      vector<string> parts = split(desc, ' ');
      assert(parts.size() == 3);
      int num = Core::lexicalCast<int>(parts[0]);
      if (atomNumber.size() > 0 && atomNumber.back() == num)
        continue;
      atomNumber.push_back(num);
      atomSymbol.push_back(parts[1]);
    }

    // Now create the structure, and expand out the orbitals.
    GaussianSet *basis = new GaussianSet;
    basis->setMolecule(&molecule);
    for (size_t i = 0; i < atomSymbol.size(); ++i) {
      string symbol = atomSymbol[i];
      Value basisFunctions = basisSet["basisFunctions"];
      Value currentFunction;
      for (size_t j = 0; j < basisFunctions.size(); ++j) {
        currentFunction = basisFunctions.get(j, 0);

        string elementType;
        if (currentFunction.isMember("elementLabel"))
          elementType = currentFunction["elementLabel"].asString();
        else if (currentFunction.isMember("elementType"))
          elementType = currentFunction["elementType"].asString();

        if (elementType == symbol)
          break;

        currentFunction = Json::nullValue;
      }

      if (currentFunction.isNull())
        break;

      Value contraction = currentFunction["basisSetContraction"];
      bool spherical = currentFunction["basisSetHarmonicType"].asString()
          == "spherical";
      for (size_t j = 0; j < contraction.size(); ++j) {
        Value contractionShell = contraction.get(j, Json::nullValue);
        string shellType;
        if (contractionShell.isMember("basisSetShell"))
          shellType = contractionShell["basisSetShell"].asString();
        else if (contractionShell.isMember("basisSetShellType"))
          shellType = contractionShell["basisSetShellType"].asString();
        Value exponent = contractionShell["basisSetExponent"];
        Value coefficient = contractionShell["basisSetCoefficient"];
        assert(exponent.size() == coefficient.size());
        GaussianSet::orbital type = GaussianSet::UU;
        if (shellType == "s")
          type = GaussianSet::S;
        else if (shellType == "p")
          type = GaussianSet::P;
        else if (shellType == "d" && spherical)
          type = GaussianSet::D5;
        else if (shellType == "d")
          type = GaussianSet::D;
        else if (shellType == "f" && spherical)
          type = GaussianSet::F7;
        else if (shellType == "f")
          type == GaussianSet::F;

        if (type != GaussianSet::UU) {
          int b = basis->addBasis(i, type);
          for (size_t k = 0; k < exponent.size(); ++k) {
            basis->addGto(b, coefficient.get(k, 0).asDouble(),
                          exponent.get(k, 0).asDouble());
          }
        }
      }
    }
    // Now to add the molecular orbital coefficients.
    Value moCoeffs = molecularOrbitals["molecularOrbital"];
    vector<double> coeffArray;
    vector<double> energyArray;
    vector<unsigned char> occArray;
    vector<unsigned int> numArray;
    for (size_t i = 0; i < moCoeffs.size(); ++i) {
      Value currentMO = moCoeffs.get(i, Json::nullValue);
      Value coeff = currentMO["moCoefficients"];
      for (size_t j = 0; j < coeff.size(); ++j)
        coeffArray.push_back(coeff.get(j, 0).asDouble());
      if (currentMO.isMember("orbitalEnergy"))
        energyArray.push_back(currentMO["orbitalEnergy"]["value"].asDouble());
      if (currentMO.isMember("orbitalOccupancy"))
        occArray.push_back(static_cast<unsigned char>(currentMO["orbitalOccupancy"].asInt()));
      if (currentMO.isMember("orbitalNumber"))
        numArray.push_back(static_cast<unsigned int>(currentMO["orbitalNumber"].asInt()));
    }
    basis->setMolecularOrbitals(coeffArray);
    basis->setMolecularOrbtitalEnergy(energyArray);
    basis->setMolecularOrbtitalOccupancy(occArray);
    basis->setMolecularOrbtitalNumber(numArray);
    basis->setElectronCount(numberOfElectrons);
    molecule.setBasisSet(basis);
  }

  // Now to see if there was a vibrational frequencies calculation.
  if (!calculationVib.isNull() && calculationVib.isObject()) {
    Value normalModes = calculationVib["calculationResults"]["normalModes"];
    if (!normalModes.isNull() && normalModes.isArray()) {
      Array<double> frequencies;
      Array<double> intensities;
      Array< Array<Vector3> > Lx;
      for (size_t i = 0; i < normalModes.size(); ++i) {
        Value mode = normalModes.get(i, "");
        frequencies.push_back(mode["normalModeFrequency"]["value"].asDouble());
        intensities.push_back(mode["normalModeInfraRedIntensity"]["value"].asDouble());
        Value lx = mode["normalModeVector"]["value"];
        if (!lx.empty() && lx.isArray()) {
          Array<Vector3> modeLx;
          modeLx.resize(lx.size() / 3);
          for (size_t k = 0; k < lx.size(); ++k)
            modeLx[k / 3][k % 3] = lx.get(k, 0).asDouble();
          Lx.push_back(modeLx);
        }
      }
      molecule.setVibrationFrequencies(frequencies);
      molecule.setVibrationIntensities(intensities);
      molecule.setVibrationLx(Lx);
    }
  }

  return true;
}

bool NWChemJson::write(std::ostream &file, const Molecule &molecule)
{
  return false;
}

vector<std::string> NWChemJson::fileExtensions() const
{
  vector<std::string> ext;
  ext.push_back("json");
  ext.push_back("nwjson");
  return ext;
}

vector<std::string> NWChemJson::mimeTypes() const
{
  vector<std::string> mime;
  mime.push_back("chemical/x-nwjson");
  return mime;
}

} // end QuantumIO namespace
} // end Avogadro namespace
<|endoftext|>


<commit_before>/***************************************************************************
 *  common/version.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2007, 2008, 2011 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <stxxl/bits/version.h>

#ifdef STXXL_BOOST_CONFIG
#include <boost/version.hpp>
#endif

#define stringify(x) #x
#define STXXL_VERSION_STRING_MA_MI_PL stringify(STXXL_VERSION_MAJOR) "." stringify(STXXL_VERSION_MINOR) "." stringify(STXXL_VERSION_PATCHLEVEL)

// version.defs gets created if a snapshot/beta/rc/release is done
#ifdef HAVE_VERSION_DEFS
#include "version.defs"
#endif

// version_svn.defs gets created if stxxl is built from SVN
#ifdef HAVE_VERSION_SVN_DEFS
#include "version_svn.defs"
#endif

__STXXL_BEGIN_NAMESPACE

int version_major()
{
    return STXXL_VERSION_MAJOR;
};

int version_minor()
{
    return STXXL_VERSION_MINOR;
}

int version_patchlevel()
{
    return STXXL_VERSION_PATCHLEVEL;
}

// FIXME: this currently only works for GNU-like systems,
//        there are no details available on windows platform

const char * get_version_string()
{
    return "STXXL"
#ifdef STXXL_VERSION_STRING_SVN_BRANCH
           " (branch: " STXXL_VERSION_STRING_SVN_BRANCH ")"
#endif
           " v"
           STXXL_VERSION_STRING_MA_MI_PL
#ifdef STXXL_VERSION_STRING_DATE
           "-" STXXL_VERSION_STRING_DATE
#endif
#ifdef STXXL_VERSION_STRING_SVN_REVISION
           " (SVN r" STXXL_VERSION_STRING_SVN_REVISION ")"
#endif
#ifdef STXXL_VERSION_STRING_PHASE
           " (" STXXL_VERSION_STRING_PHASE ")"
#else
           " (prerelease)"
#endif
#ifdef STXXL_VERSION_STRING_COMMENT
           " (" STXXL_VERSION_STRING_COMMENT ")"
#endif
#ifdef __MCSTL__
           " + MCSTL"
#ifdef MCSTL_VERSION_STRING_DATE
           " " MCSTL_VERSION_STRING_DATE
#endif
#ifdef MCSTL_VERSION_STRING_SVN_REVISION
           " (SVN r" MCSTL_VERSION_STRING_SVN_REVISION ")"
#endif
#endif
#ifdef STXXL_BOOST_CONFIG
           " + Boost "
#define Y(x) # x
#define X(x) Y(x)
           X(BOOST_VERSION)
#undef X
#undef Y
#endif
    ;
}

__STXXL_END_NAMESPACE

// vim: et:ts=4:sw=4
<commit_msg>fix stringify() macro, needs to be nested<commit_after>/***************************************************************************
 *  common/version.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2007, 2008, 2011 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <stxxl/bits/version.h>

#ifdef STXXL_BOOST_CONFIG
#include <boost/version.hpp>
#endif

#define stringify_(x) #x
#define stringify(x) stringify_(x)
#define STXXL_VERSION_STRING_MA_MI_PL stringify(STXXL_VERSION_MAJOR) "." stringify(STXXL_VERSION_MINOR) "." stringify(STXXL_VERSION_PATCHLEVEL)

// version.defs gets created if a snapshot/beta/rc/release is done
#ifdef HAVE_VERSION_DEFS
#include "version.defs"
#endif

// version_svn.defs gets created if stxxl is built from SVN
#ifdef HAVE_VERSION_SVN_DEFS
#include "version_svn.defs"
#endif

__STXXL_BEGIN_NAMESPACE

int version_major()
{
    return STXXL_VERSION_MAJOR;
};

int version_minor()
{
    return STXXL_VERSION_MINOR;
}

int version_patchlevel()
{
    return STXXL_VERSION_PATCHLEVEL;
}

// FIXME: this currently only works for GNU-like systems,
//        there are no details available on windows platform

const char * get_version_string()
{
    return "STXXL"
#ifdef STXXL_VERSION_STRING_SVN_BRANCH
           " (branch: " STXXL_VERSION_STRING_SVN_BRANCH ")"
#endif
           " v"
           STXXL_VERSION_STRING_MA_MI_PL
#ifdef STXXL_VERSION_STRING_DATE
           "-" STXXL_VERSION_STRING_DATE
#endif
#ifdef STXXL_VERSION_STRING_SVN_REVISION
           " (SVN r" STXXL_VERSION_STRING_SVN_REVISION ")"
#endif
#ifdef STXXL_VERSION_STRING_PHASE
           " (" STXXL_VERSION_STRING_PHASE ")"
#else
           " (prerelease)"
#endif
#ifdef STXXL_VERSION_STRING_COMMENT
           " (" STXXL_VERSION_STRING_COMMENT ")"
#endif
#ifdef __MCSTL__
           " + MCSTL"
#ifdef MCSTL_VERSION_STRING_DATE
           " " MCSTL_VERSION_STRING_DATE
#endif
#ifdef MCSTL_VERSION_STRING_SVN_REVISION
           " (SVN r" MCSTL_VERSION_STRING_SVN_REVISION ")"
#endif
#endif
#ifdef STXXL_BOOST_CONFIG
           " + Boost "
#define Y(x) # x
#define X(x) Y(x)
           X(BOOST_VERSION)
#undef X
#undef Y
#endif
    ;
}

__STXXL_END_NAMESPACE

// vim: et:ts=4:sw=4
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCell.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkCell.h"

// Construct cell.
vtkCell::vtkCell()
{
  this->Points = vtkPoints::New();
  this->PointIds = vtkIdList::New();
}

vtkCell::~vtkCell()
{
  this->Points->Delete();
  this->PointIds->Delete();
}

//
// Instantiate cell from outside
//
void vtkCell::Initialize(int npts, int *pts, vtkPoints *p)
{
  this->PointIds->Reset();
  this->Points->Reset();

  for (int i=0; i<npts; i++)
    {
    this->PointIds->InsertId(i,pts[i]);
    this->Points->InsertPoint(i,p->GetPoint(pts[i]));
    }
}

void vtkCell::ShallowCopy(vtkCell *c)
{
  this->Points->ShallowCopy(c->Points);
  this->PointIds->ShallowCopy(c->PointIds);
}

void vtkCell::DeepCopy(vtkCell *c)
{
  this->Points->DeepCopy(c->Points);
  this->PointIds->DeepCopy(c->PointIds);
}

#define VTK_RIGHT 0
#define VTK_LEFT 1
#define VTK_MIDDLE 2

// Bounding box intersection modified from Graphics Gems Vol I.
// Note: the intersection ray is assumed normalized, such that
// valid intersections can only occur between [0,1]. Method returns non-zero
// value if bounding box is hit. Origin[3] starts the ray, dir[3] is the
// components of the ray in the x-y-z directions, coord[3] is the location
// of hit, and t is the parametric coordinate along line.
char vtkCell::HitBBox (float bounds[6], float origin[3], float dir[3],
                      float coord[3], float& t)
{
  char    inside=1;
  char    quadrant[3];
  int     i, whichPlane=0;
  float   maxT[3], candidatePlane[3];
//
//  First find closest planes
//
  for (i=0; i<3; i++)
    {
    if ( origin[i] < bounds[2*i] )
      {
      quadrant[i] = VTK_LEFT;
      candidatePlane[i] = bounds[2*i];
      inside = 0;
      }
    else if ( origin[i] > bounds[2*i+1] )
      {
      quadrant[i] = VTK_RIGHT;
      candidatePlane[i] = bounds[2*i+1];
      inside = 0;
      }
    else
      {
      quadrant[i] = VTK_MIDDLE;
      }
    }
//
//  Check whether origin of ray is inside bbox
//
  if (inside)
    {
    coord[0] = origin[0];
    coord[1] = origin[1];
    coord[2] = origin[2];
    t = 0;
    return 1;
    }

//
//  Calculate parametric distances to plane
//
  for (i=0; i<3; i++)
    {
    if ( quadrant[i] != VTK_MIDDLE && dir[i] != 0.0 )
      {
      maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
      }
    else
      {
      maxT[i] = -1.0;
      }
    }
//
//  Find the largest parametric value of intersection
//
  for (i=0; i<3; i++)
    {
    if ( maxT[whichPlane] < maxT[i] )
      {
      whichPlane = i;
      }
    }
//
//  Check for valid intersection along line
//
  if ( maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0 )
    {
    return 0;
    }
  else
    {
    t = maxT[whichPlane];
    }
//
//  Intersection point along line is okay.  Check bbox.
//
  for (i=0; i<3; i++)
    {
    if (whichPlane != i)
      {
      coord[i] = origin[i] + maxT[whichPlane]*dir[i];
      if ( coord[i] < bounds[2*i] || coord[i] > bounds[2*i+1] )
	{
        return 0;
	}
      }
    else
      {
      coord[i] = candidatePlane[i];
      }
    }

    return 1;
}

// Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Return pointer
// to array of six float values.
float *vtkCell::GetBounds ()
{
  float *x;
  int i, numPts=this->Points->GetNumberOfPoints();

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] =  VTK_LARGE_FLOAT;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_LARGE_FLOAT;

  for (i=0; i<numPts; i++)
    {
    x = this->Points->GetPoint(i);

    this->Bounds[0] = (x[0] < this->Bounds[0] ? x[0] : this->Bounds[0]);
    this->Bounds[1] = (x[0] > this->Bounds[1] ? x[0] : this->Bounds[1]);
    this->Bounds[2] = (x[1] < this->Bounds[2] ? x[1] : this->Bounds[2]);
    this->Bounds[3] = (x[1] > this->Bounds[3] ? x[1] : this->Bounds[3]);
    this->Bounds[4] = (x[2] < this->Bounds[4] ? x[2] : this->Bounds[4]);
    this->Bounds[5] = (x[2] > this->Bounds[5] ? x[2] : this->Bounds[5]);

    }
  return this->Bounds;
}

// Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Copy result into
// user provided array.
void vtkCell::GetBounds(float bounds[6])
{
  this->GetBounds();
  for (int i=0; i < 6; i++)
    {
    bounds[i] = this->Bounds[i];
    }
}

// Compute Length squared of cell (i.e., bounding box diagonal squared).
float vtkCell::GetLength2 ()
{
  float diff, l=0.0;
  int i;

  this->GetBounds();
  for (i=0; i<3; i++)
    {
    diff = this->Bounds[2*i+1] - this->Bounds[2*i];
    l += diff * diff;
    }

  return l;
}

// Return center of the cell in parametric coordinates.
// Note that the parametric center is not always located
// at (0.5,0.5,0.5). The return value is the subId that
// the center is in (if a composite cell). If you want the
// center in x-y-z space, invoke the EvaluateLocation() method.
int vtkCell::GetParametricCenter(float pcoords[3])
{
  pcoords[0] = pcoords[1] = pcoords[2] = 0.5;
  return 0;
}

void vtkCell::PrintSelf(ostream& os, vtkIndent indent)
{
  int numIds=this->PointIds->GetNumberOfIds();

  vtkObject::PrintSelf(os,indent);

  os << indent << "Number Of Points: " << numIds << "\n";

  if ( numIds > 0 )
    {
    float *bounds=this->GetBounds();

    os << indent << "Bounds: \n";
    os << indent << "  Xmin,Xmax: (" << bounds[0] << ", " << bounds[1] << ")\n";
    os << indent << "  Ymin,Ymax: (" << bounds[2] << ", " << bounds[3] << ")\n";
    os << indent << "  Zmin,Zmax: (" << bounds[4] << ", " << bounds[5] << ")\n";

    os << indent << "  Point ids are: ";
    for (int i=0; i < numIds; i++)
      {
      os << this->PointIds->GetId(i);
      if ( i && !(i % 12) )
	{
	os << "\n\t";
	}
      else
	{
	if ( i != (numIds-1) )
	  {
	  os << ", ";
	  }
	}
      }
    os << indent << "\n";
    }
}
<commit_msg>ENH:Improved IdList performance<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkCell.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkCell.h"

// Construct cell.
vtkCell::vtkCell()
{
  this->Points = vtkPoints::New();
  this->PointIds = vtkIdList::New();
}

vtkCell::~vtkCell()
{
  this->Points->Delete();
  this->PointIds->Delete();
}

//
// Instantiate cell from outside
//
void vtkCell::Initialize(int npts, int *pts, vtkPoints *p)
{
  this->PointIds->Reset();
  this->Points->Reset();

  for (int i=0; i<npts; i++)
    {
    this->PointIds->InsertId(i,pts[i]);
    this->Points->InsertPoint(i,p->GetPoint(pts[i]));
    }
}

void vtkCell::ShallowCopy(vtkCell *c)
{
  this->Points->ShallowCopy(c->Points);
  this->PointIds->DeepCopy(c->PointIds);
}

void vtkCell::DeepCopy(vtkCell *c)
{
  this->Points->DeepCopy(c->Points);
  this->PointIds->DeepCopy(c->PointIds);
}

#define VTK_RIGHT 0
#define VTK_LEFT 1
#define VTK_MIDDLE 2

// Bounding box intersection modified from Graphics Gems Vol I.
// Note: the intersection ray is assumed normalized, such that
// valid intersections can only occur between [0,1]. Method returns non-zero
// value if bounding box is hit. Origin[3] starts the ray, dir[3] is the
// components of the ray in the x-y-z directions, coord[3] is the location
// of hit, and t is the parametric coordinate along line.
char vtkCell::HitBBox (float bounds[6], float origin[3], float dir[3],
                      float coord[3], float& t)
{
  char    inside=1;
  char    quadrant[3];
  int     i, whichPlane=0;
  float   maxT[3], candidatePlane[3];
//
//  First find closest planes
//
  for (i=0; i<3; i++)
    {
    if ( origin[i] < bounds[2*i] )
      {
      quadrant[i] = VTK_LEFT;
      candidatePlane[i] = bounds[2*i];
      inside = 0;
      }
    else if ( origin[i] > bounds[2*i+1] )
      {
      quadrant[i] = VTK_RIGHT;
      candidatePlane[i] = bounds[2*i+1];
      inside = 0;
      }
    else
      {
      quadrant[i] = VTK_MIDDLE;
      }
    }
//
//  Check whether origin of ray is inside bbox
//
  if (inside)
    {
    coord[0] = origin[0];
    coord[1] = origin[1];
    coord[2] = origin[2];
    t = 0;
    return 1;
    }

//
//  Calculate parametric distances to plane
//
  for (i=0; i<3; i++)
    {
    if ( quadrant[i] != VTK_MIDDLE && dir[i] != 0.0 )
      {
      maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
      }
    else
      {
      maxT[i] = -1.0;
      }
    }
//
//  Find the largest parametric value of intersection
//
  for (i=0; i<3; i++)
    {
    if ( maxT[whichPlane] < maxT[i] )
      {
      whichPlane = i;
      }
    }
//
//  Check for valid intersection along line
//
  if ( maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0 )
    {
    return 0;
    }
  else
    {
    t = maxT[whichPlane];
    }
//
//  Intersection point along line is okay.  Check bbox.
//
  for (i=0; i<3; i++)
    {
    if (whichPlane != i)
      {
      coord[i] = origin[i] + maxT[whichPlane]*dir[i];
      if ( coord[i] < bounds[2*i] || coord[i] > bounds[2*i+1] )
	{
        return 0;
	}
      }
    else
      {
      coord[i] = candidatePlane[i];
      }
    }

    return 1;
}

// Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Return pointer
// to array of six float values.
float *vtkCell::GetBounds ()
{
  float *x;
  int i, numPts=this->Points->GetNumberOfPoints();

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] =  VTK_LARGE_FLOAT;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_LARGE_FLOAT;

  for (i=0; i<numPts; i++)
    {
    x = this->Points->GetPoint(i);

    this->Bounds[0] = (x[0] < this->Bounds[0] ? x[0] : this->Bounds[0]);
    this->Bounds[1] = (x[0] > this->Bounds[1] ? x[0] : this->Bounds[1]);
    this->Bounds[2] = (x[1] < this->Bounds[2] ? x[1] : this->Bounds[2]);
    this->Bounds[3] = (x[1] > this->Bounds[3] ? x[1] : this->Bounds[3]);
    this->Bounds[4] = (x[2] < this->Bounds[4] ? x[2] : this->Bounds[4]);
    this->Bounds[5] = (x[2] > this->Bounds[5] ? x[2] : this->Bounds[5]);

    }
  return this->Bounds;
}

// Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Copy result into
// user provided array.
void vtkCell::GetBounds(float bounds[6])
{
  this->GetBounds();
  for (int i=0; i < 6; i++)
    {
    bounds[i] = this->Bounds[i];
    }
}

// Compute Length squared of cell (i.e., bounding box diagonal squared).
float vtkCell::GetLength2 ()
{
  float diff, l=0.0;
  int i;

  this->GetBounds();
  for (i=0; i<3; i++)
    {
    diff = this->Bounds[2*i+1] - this->Bounds[2*i];
    l += diff * diff;
    }

  return l;
}

// Return center of the cell in parametric coordinates.
// Note that the parametric center is not always located
// at (0.5,0.5,0.5). The return value is the subId that
// the center is in (if a composite cell). If you want the
// center in x-y-z space, invoke the EvaluateLocation() method.
int vtkCell::GetParametricCenter(float pcoords[3])
{
  pcoords[0] = pcoords[1] = pcoords[2] = 0.5;
  return 0;
}

void vtkCell::PrintSelf(ostream& os, vtkIndent indent)
{
  int numIds=this->PointIds->GetNumberOfIds();

  vtkObject::PrintSelf(os,indent);

  os << indent << "Number Of Points: " << numIds << "\n";

  if ( numIds > 0 )
    {
    float *bounds=this->GetBounds();

    os << indent << "Bounds: \n";
    os << indent << "  Xmin,Xmax: (" << bounds[0] << ", " << bounds[1] << ")\n";
    os << indent << "  Ymin,Ymax: (" << bounds[2] << ", " << bounds[3] << ")\n";
    os << indent << "  Zmin,Zmax: (" << bounds[4] << ", " << bounds[5] << ")\n";

    os << indent << "  Point ids are: ";
    for (int i=0; i < numIds; i++)
      {
      os << this->PointIds->GetId(i);
      if ( i && !(i % 12) )
	{
	os << "\n\t";
	}
      else
	{
	if ( i != (numIds-1) )
	  {
	  os << ", ";
	  }
	}
      }
    os << indent << "\n";
    }
}
<|endoftext|>


<commit_before>#include "console.h"

#include <iostream>
#include <readline/readline.h>
#include <readline/history.h>

#include "defs.h"
#include "command.h"

Console::Console(){

	shell = new Shell();
	handler = new Handler(shell);
}

Console::~Console(){

	delete handler;
	delete shell;
}

bool Console::start(){

	while(!handler->isTerminated()){

		// getting the current path
		const char* cur_path = shell->getPath();
		// printing the prompt
		std::cout << PROMPT1 << cur_path << PROMPT2;

		// reading the line
		char line[LINE_SIZE];
		std::cin.getline(line, LINE_SIZE);

		// creating new Command object
		// TODO make static?
		//Command* command = new Command(line);
		//handler->execute(*command);

		Command command(line);

		//have handler object to execute the command
		handler->execute(command);

	}

	return true;
}<commit_msg>using GNU readline and the arrows work as in bash (command history)<commit_after>#include "console.h"

#include <iostream>
#include <readline/readline.h>
#include <readline/history.h>

#include "defs.h"
#include "command.h"

Console::Console(){

	shell = new Shell();
	handler = new Handler(shell);
}

Console::~Console(){

	delete handler;
	delete shell;
}

bool Console::start(){

	while(!handler->isTerminated()){

		// getting the current path
		const char* cur_path = shell->getPath();
		// printing the prompt
		std::cout << PROMPT1 << cur_path << PROMPT2;

		char *line=(char*)NULL;

		/***using GNU readline***/

		//checking if line is empty and if it is not it frees it and reallocates memory
		if (line){
        	delete line;
      		line = (char *)NULL;
    	}
		//getting the line
  		line = readline ("");

 		//adding it to history (you can use the arrows to navigate through history)
 	    if (line && *line){
    		add_history (line);
		}

		// creating new Command object
		Command command(line);

		//have handler object to execute the command
		handler->execute(command);

	}

	return true;
}<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : ABC085B_.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/1/31 21:37:45
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  int N;
  cin >> N;
  vector<int> d(N);
  for (auto i = 0; i < N; ++i)
  {
    cin >> d[i];
  }
  sort(d.begin(), d.end());
  unique(d.begin(), d.end());
  cout << d.size() << endl;
}
<commit_msg>submit ABC085B_.cpp to 'ABC085B - Kagami Mochi' (language-test-202001) [C++ (GCC 9.2.1)]<commit_after>#define DEBUG 1
/**
 * File    : ABC085B_.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/1/31 21:37:45
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

int main()
{
  int N;
  cin >> N;
  vector<int> d(N);
  for (auto i = 0; i < N; ++i)
  {
    cin >> d[i];
  }
  sort(d.begin(), d.end());
  d.erase(unique(d.begin(), d.end()), d.end());
  cout << d.size() << endl;
}
<|endoftext|>