/***************************************************************************
                             -------------------
    cvs         : methods.cc
    begin       : Sun Jan 16 2005
    copyright   : (C) 2002, 2003, 2005 by Fabian Kaiser and Christian Stimming
    email       : fabian@openhbci.de

 ***************************************************************************
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library 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     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
 *   MA  02111-1307  USA                                                   *
 *                                                                         *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "ktoblzcheck.h"
#include <fstream>
#include <iostream>
#include <algorithm>

// The actual algorithms for number checking are there
#include "algorithms.h"

// using namespace std;  // -- not needed

// Each method is one function. The mapping of method identification
// to function is done by the cb_funcs[] array down at the end of this
// file. At runtime, the cb_funcs[] array will be inserted into a hash
// table, so that the lookup of each method's function will be
// *really* fast.
//
// When adding a new method, do this:
//
// 1. Write a method_XY() function similar to the ones existing here.
//
// 2. Add one additional line to the cb_funcs[] array down at the end
// of this file.
//
// 3. That's it!

AccountNumberCheck::Result method_00(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_01(const int *account, int *weight)
{
    number2Array("1731731730", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_02(const int *account, int *weight)
{
    number2Array("2987654320", weight);
    return algo02(11, weight, 10, account, 0, 8);
}

AccountNumberCheck::Result method_03(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    return algo01(10, weight, false, 10, account);
}

// this is method "02" using modified weight
AccountNumberCheck::Result method_04(const int *account, int *weight)
{
    number2Array("4327654320", weight);
    return algo02(11, weight, 10, account, 0, 8);
}

AccountNumberCheck::Result method_05(const int *account, int *weight)
{
    number2Array("1371371370", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_06(const int *account, int *weight)
{
    number2Array("4327654320", weight);
    return algo01(11, weight, false, 10, account);
}

// this is method "02" using modified weight
AccountNumberCheck::Result method_07(const int *account, int *weight)
{
    number2Array("0987654320", weight);
    weight[0] = 10;
    return algo02(11, weight, 10, account, 0, 8);
}

AccountNumberCheck::Result method_08(const int *account, int *weight)
{
    if (atol(array2Number(account).c_str()) < 60000) {
        return AccountNumberCheck::OK;
    }
    number2Array("2121212120", weight);
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_09(const int *account, int *weight)
{
    // no calculation -> no error
    return AccountNumberCheck::OK;
}

AccountNumberCheck::Result method_10(const int *account, int *weight)
{
    number2Array("987654320", weight);
    weight[0] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_11(const int *account, int *weight)
{
    number2Array("987654320", weight);
    weight[0] = 10;
    int tmp = algo03(11, weight, false, account, 0, 9);

    // Code by Erik Kerger:
    if (tmp > 0) {  //if result == 0 then check is 0 too
        tmp = 11 - tmp;
    }
    if (10 == tmp) { //use 9 instead of 0
        tmp = 9;
    } else {
        tmp = tmp % 10;
    }
    //tmp = (11 - tmp) % 10;
    //if (10 == tmp)
    // tmp = 9;

    if (tmp == account[9]) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

AccountNumberCheck::Result method_12(const int *account, int *weight)
{
    // not used
    return AccountNumberCheck::UNKNOWN;
}

AccountNumberCheck::Result method_13(const int *account, int *weight)
{
    number2Array("121212000", weight);
    if (algo01(10, weight, true, 8, account) != AccountNumberCheck::OK) {
        // shift left, add 00 as subaccount id and try again
        int account_buf[10];
        number2Array(array2Number(account).substr(2) + "00", account_buf);
        if (AccountNumberCheck::OK != algo01(10, weight, true, 8, account_buf)) {
            return AccountNumberCheck::ERROR;
        }
    }
    return AccountNumberCheck::OK;
}

// this is method "02" using modified weight
AccountNumberCheck::Result method_14(const int *account, int *weight)
{
    number2Array("0007654320", weight);
    return algo02(11, weight, 10, account, 3, 8);
}

AccountNumberCheck::Result method_15(const int *account, int *weight)
{
    number2Array("54320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_16(const int *account, int *weight)
{
    number2Array("4327654320", weight);
    int tmp = algo03(11, weight, false, account, 0, 9);
    tmp = tmp % 11;
    if (1 == tmp && account[8] == account[9]) {
        return AccountNumberCheck::OK;
    } else {
        return algo01(11, weight, false, 10, account);
    }
}

// Added by Jens Gecius, validated with one test accountID
AccountNumberCheck::Result method_17(const int *account, int *weight)
{
    number2Array("0121212000", weight);
    int tmp = algo03a(weight, true, account, 1, 6);
    tmp = (tmp - 1) % 11;
    tmp = 10 - tmp;
    if (10 == tmp) {
        tmp = 0;
    }
    if (account[7] == tmp) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
    // FIXME
}

AccountNumberCheck::Result method_18(const int *account, int *weight)
{
    number2Array("3179317930", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_19(const int *account, int *weight)
{
    number2Array("1987654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_20(const int *account, int *weight)
{
    number2Array("3987654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_21(const int *account, int *weight)
{
    int res[10];
    number2Array("2121212120", weight);

    // mult the weight with the account id
    multArray(account, weight, res);

    // for 00,...: calc the crossfoot for each value
    crossFoot(res);

    // add all values
    int result = add_10(res);

    // crossfoot for the result until only one digit is left
    while (result > 9) {
        int tmp = result % 10;
        result /= 10;
        result += tmp;
    }
    result = 10 - result;

    if (result == account[9]) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

AccountNumberCheck::Result method_22(const int *account, int *weight)
{
    number2Array("3131313130", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_23(const int *account, int *weight)
{
    number2Array("7654320000", weight);
    int tmp = algo03(11, weight, false, account, 0, 5);
    if (0 == tmp && 0 == account[6]) {
        return AccountNumberCheck::OK;
    }
    if (1 == tmp && account[5] == account[6]) {
        return AccountNumberCheck::OK;
    }
    if (1 < tmp && account[6] == (11 - tmp)) {
        return AccountNumberCheck::OK;
    }

    return AccountNumberCheck::ERROR;
}

// rewrite of method_24(), moved part of the code from algorithms.c old algo05() here
AccountNumberCheck::Result method_24(const int *account, int *weight)
{
    // copy to keep interface array const
    int account_buf[10];
    for (int i = 0; i <= 9; i++) {
        account_buf[i] = account[i];
    }

    if (2 < account_buf[0] && 7 > account_buf[0]) {
        account_buf[0] = 0;
    }
    if (9 == account_buf[0]) {
        account_buf[0] = 0;
        account_buf[1] = 0;
        account_buf[2] = 0;
        if (0 == account[3]) {
            return AccountNumberCheck::ERROR;
        }
    }

    // check how many leading "0", shift weight to right
    //int start=0;
    std::string weightString = "";
    for (int i = 0; i < 10; i++) {
        if (0 == account_buf[i]) {
            weightString += "0";
        } else {
            //start = i;
            break;
        }
    }
    weightString += "123123123";
    weightString = weightString.substr(0, 9) + "0";

    number2Array(weightString, weight);

    int result = algo05(11, 10, weight, account_buf, 0, 8);
    if (result == account_buf[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// Added by Jens Gecius, validated with one test accountID
AccountNumberCheck::Result method_25(const int *account, int *weight)
{
    number2Array("987654320", weight);
    int result = algo03(11, weight, false, account, 1, 8);
    result = 11 - result;
    if (result == 11) {
        result = 0;
    }
    if (result == 10 && account[9] == 0 && (account[1] == 8 || account[1] == 9)) {
        return AccountNumberCheck::OK;
    }
    if (result == account[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// Added by Jens Gecius, validated with three test accountIDs and one own accountID
AccountNumberCheck::Result method_26(const int *account, int *weight)
{
    number2Array("2765432000", weight);
    if (account[0] == 0 && account[1] == 0) {
        int account_buf[10];
        number2Array(array2Number(account).substr(2) + "00", account_buf);
        return algo01(11, weight, false, 8, account_buf);
    } else {
        return algo01(11, weight, false, 8, account);
    }
}

// Added by Jens Gecius, validated with nine own accountIDs + testaccountID (six > 1000000000)
AccountNumberCheck::Result method_27(const int *account, int *weight)
{
    int transform[6][10] =
    { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // zero for non-transform [0][x]
      {0, 1, 5, 9, 3, 7, 4, 8, 2, 6}, // first transform line   [1][x]
      {0, 1, 7, 6, 9, 8, 3, 2, 5, 4}, // second transform line  [2][x]
      {0, 1, 8, 4, 6, 2, 9, 5, 7, 3}, // third transform line   [3][x]
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, // fourth transform line  [4][x]
      {1, 4, 3, 2, 1, 4, 3, 2, 1, 0} }; // which transform line

    if (atol(array2Number(account).c_str()) < 1000000000) {
        number2Array("2121212120", weight);
        return algo01(10, weight, true, 10, account);
    } else {
        // iterated transformation
        return algo07(account, transform);
    }
    //return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_28(const int *account, int *weight)
{
    number2Array("8765432000", weight);
    return algo01(11, weight, false, 8, account);
}

// Added by Jens Gecius, validated with test accountID
AccountNumberCheck::Result method_29(const int *account, int *weight)
{
    int transform[6][10] =
    { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // zero for non-transform [0][x]
      {0, 1, 5, 9, 3, 7, 4, 8, 2, 6}, // first transform line   [1][x]
      {0, 1, 7, 6, 9, 8, 3, 2, 5, 4}, // second transform line  [2][x]
      {0, 1, 8, 4, 6, 2, 9, 5, 7, 3}, // third transform line   [3][x]
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, // fourth transform line  [4][x]
      {1, 4, 3, 2, 1, 4, 3, 2, 1, 0} }; // which transform line

    return algo07(account, transform);
}

AccountNumberCheck::Result method_30(const int *account, int *weight)
{
    number2Array("2000012120", weight);
    return algo01(10, weight, false, 10, account);
}

// Changed by Jens Gecius, validated with two test accountIDs
AccountNumberCheck::Result method_31(const int *account, int *weight)
{
    number2Array("1234567890", weight);
    int result = algo03(11, weight, false, account, 0, 9);

    // no rest after division by modulus (in algo03)?
    // then the the result will be 0! (as it is... removed next two lines
    // as there is no further calculation
    // if (0 == result)
    //  result = 11;

    // next two lines removed, as 10 can never be a digit in accountID
    // if (10 == result)
    //  return AccountNumberCheck::ERROR;

    if (result == account[9]) {
        return AccountNumberCheck::OK;
    }
    // to stay in line with convention so far, remove next line
    // else
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_32(const int *account, int *weight)
{
    number2Array("0007654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_33(const int *account, int *weight)
{
    number2Array("0000654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_34(const int *account, int *weight)
{
    number2Array("7905842000", weight);
    weight[2] = 10;
    return algo01(11, weight, false, 8, account);
}

// Added by Jens Gecius, not validated due to missing bank using this algo
AccountNumberCheck::Result method_35(const int *account, int *weight)
{
    number2Array("0987654320", weight);
    weight[0] = 10;
    int result = algo03(11, weight, false, account, 0, 9);
    if (result == 10 && account[9] == account[8]) {
        return AccountNumberCheck::OK;
    }
    if (result == account[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_36(const int *account, int *weight)
{
    number2Array("0000058420", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_37(const int *account, int *weight)
{
    number2Array("0000058420", weight);
    weight[4] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_38(const int *account, int *weight)
{
    number2Array("0009058420", weight);
    weight[4] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_39(const int *account, int *weight)
{
    number2Array("0079058420", weight);
    weight[4] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_40(const int *account, int *weight)
{
    number2Array("6379058420", weight);
    weight[4] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_41(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    if (9 == account[3]) {
        weight[0] = 0;
        weight[1] = 0;
        weight[2] = 0;
    }
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_42(const int *account, int *weight)
{
    number2Array("0987654320", weight);
    return algo01(11, weight, false, 10, account);
}

// Added by Jens Gecius, validated with two test accountIDs
AccountNumberCheck::Result method_43(const int *account, int *weight)
{
    number2Array("9876543210", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_44(const int *account, int *weight)
{
    number2Array("0000058420", weight);
    weight[4] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_45(const int *account, int *weight)
{
    // some numbers do not have a checksum
    if (0 == account[0] || 1 == account[4]) {
        return AccountNumberCheck::OK;
    }

    number2Array("2121212120", weight);
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_46(const int *account, int *weight)
{
    number2Array("0065432000", weight);
    return algo01(11, weight, false, 8, account);
}

AccountNumberCheck::Result method_47(const int *account, int *weight)
{
    number2Array("0006543200", weight);
    return algo01(11, weight, false, 9, account);
}

AccountNumberCheck::Result method_48(const int *account, int *weight)
{
    number2Array("0076543200", weight);
    return algo01(11, weight, false, 9, account);
}

AccountNumberCheck::Result method_49(const int *account, int *weight)
{
    // try with method == 00
    number2Array("2121212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    } else {
        // on error try with method == 01
        number2Array("1731731730", weight);
        return algo01(10, weight, false, 10, account);
    }
}

AccountNumberCheck::Result method_50(const int *account, int *weight)
{
    number2Array("7654320000", weight);
    AccountNumberCheck::Result tmp = algo01(11, weight, false, 7, account);
    if (AccountNumberCheck::OK == tmp) {
        return AccountNumberCheck::OK;
    } else {
        // on error, shift left by 3 and try again
        int account_buf[10];
        number2Array(array2Number(account).substr(3) + "000", account_buf);
        return algo01(11, weight, false, 7, account_buf);
    }
}

// This is not an individual method, but this code is quite popolar.
// successfully checked with positive and negative samples.
AccountNumberCheck::Result method_51_exception(const int *account, int *weight)
{
    number2Array("0087654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;      // Variant 1
    }
    number2Array("0987654320", weight);
    weight[0] = 10;
    return algo01(11, weight, false, 10, account);  // Variant 2
}

// Added by Jens Gecius, validated with six test accountIDs
// method 51 was extended for due-date 2013-06-03
AccountNumberCheck::Result method_51(const int *account, int *weight)
{
    // exception "Ausnahme f. Sachkonten"
    if (9 == account[2]) {
        return method_51_exception(account, weight);
    }

    number2Array("0007654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK; // Method A
    }
    number2Array("0000654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK; // Method B
    }
    number2Array("0001212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK; // Method C
    }
    if (7 == account[9] || 8 == account[9] || 9 == account[9]) {
        return AccountNumberCheck::ERROR; // Invalid IDs
    }
    number2Array("0000654320", weight);
    return algo01(7, weight, false, 10, account); // Method D
}

AccountNumberCheck::Result method_52(const int *account, int *weight, const std::string &accountId,
                                     const std::string &bankId)
{
    // Changed by Jens Gecius, only 10 digit accountIDs starting with "9",
    // *NOT* validated
    if (10 == accountId.length() && 9 == account[0]) {
        number2Array("3987654320", weight);
        return algo01(11, weight, false, 10, account);
    }
    return algo04(bankId, accountId);
    // return UNKNOWN;
    //	return algo04(bankId, accountId);
}

// Added by Jens Gecius, *NOT* validated
AccountNumberCheck::Result method_53(const int *account, int *weight, const std::string &accountId,
                                     const std::string &bankId)
{
    // Changed by Jens Gecius, only 10 digit accountIDs starting with "9",
    // *NOT* validated
    if (10 == accountId.length() && 9 == account[0]) {
        number2Array("3987654320", weight);
        return algo01(11, weight, false, 10, account);
    }
    // Hint by Erik Kerger <erik@kedo.com>, 2004-08-14: return
    // algo04a instead of algo04
    return algo04a(bankId, accountId);
}

AccountNumberCheck::Result method_54(const int *account, int *weight)
{
    // ids must start with 49
    if (!(4 == account[0] && 9 == account[1])) {
        return AccountNumberCheck::ERROR;
    }

    number2Array("0027654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_55(const int *account, int *weight)
{
    number2Array("8787654320", weight);
    return algo01(11, weight, false, 10, account);
}

// Added by Jens Gecius, validated with two test accountIDs
AccountNumberCheck::Result method_56(const int *account, int *weight)
{
    number2Array("4327654320", weight);
    int result = 11 - algo03(11, weight, false, account, 0, 9);
    // Ausnahme fuer 9 als erste Stelle; nach Hinweis von Michael
    // Plugge <m.plugge@fh-mannheim.de>
    if (result > 9) {
        if (account[0] == 9) {
            if (result == 10) {
                result = 7;
            } else {
                result = 8;
            }
        } else {
            return AccountNumberCheck::ERROR;
        }
    }
    if (result == account[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// Method 57 was last modified for due date 2013-09-09
AccountNumberCheck::Result method_57(const int *account, int *weight)
{
    int firstTwo = atoi(array2Number(account).substr(0, 2).c_str());
    int firstSix = atoi(array2Number(account).substr(0, 6).c_str());
    if (firstTwo == 0) {
        return AccountNumberCheck::ERROR;
    }
    if ((firstTwo >= 64 && firstTwo <= 66)
        || (firstTwo >= 73 && firstTwo <= 82)
        || firstTwo == 51 || firstTwo == 55 || firstTwo == 61
        || firstTwo == 70 || firstTwo == 88
        || firstTwo == 94 || firstTwo == 95) {      // Variante 1
        if ((777777 == firstSix) || (888888 == firstSix)) { // Exception for variant 1
            return AccountNumberCheck::OK;
        }
        number2Array("1212121210", weight);
        return algo01(10, weight, true, 10, account);
    } else if ((firstTwo >= 32 && firstTwo <= 39)
               || (firstTwo >= 41 && firstTwo <= 49)
               || (firstTwo >= 52 && firstTwo <= 54)
               || (firstTwo >= 56 && firstTwo <= 60)
               || (firstTwo >= 67 && firstTwo <= 69)
               || (firstTwo >= 83 && firstTwo <= 87)
               || (firstTwo >= 96 && firstTwo <= 98)
               || firstTwo == 62 || firstTwo == 63 || firstTwo == 71
               || firstTwo == 72 || firstTwo == 89
               || firstTwo == 90 || firstTwo == 92 || firstTwo == 93) { // Variante 2
        number2Array("1201212121", weight);
        return algo01(10, weight, true, 3, account);
    } else if (firstTwo == 40 || firstTwo == 50
               || firstTwo == 91 || firstTwo == 99) { // Variante 3
        return AccountNumberCheck::OK;  // method 09
    } else if (firstTwo >= 01 && firstTwo <= 31) {      // Variante 4
        int threeAndFour = atoi(array2Number(account).substr(2, 2).c_str());
        if (firstSix == 18512 && account[6] == 5 && account[7] == 4
            && account[8] == 3 && account[9] == 4) { // Exception for "0185125434"
            return AccountNumberCheck::OK;
        }
        if (threeAndFour >= 1 && threeAndFour <= 12
            && atoi(array2Number(account).substr(6, 3).c_str()) < 500) {
            return AccountNumberCheck::OK;
        } else {
            return AccountNumberCheck::ERROR;
        }
    }
    return AccountNumberCheck::ERROR;
}

// Added by Jens Gecius, validated with four test accountIDs
AccountNumberCheck::Result method_58(const int *account, int *weight)
{
    if (0 == atoi(array2Number(account).substr(0, 5).c_str())) {
        return AccountNumberCheck::ERROR;
    }

    // this is method "02" using modified weight
    number2Array("0000654320", weight);
    return algo02(11, weight, 10, account, 4, 8);
}

AccountNumberCheck::Result method_59(const int *account, int *weight)
{
    // ids less than 9 digits can not be checked
    if (0 == account[0] && 0 == account[1]) {
        return AccountNumberCheck::OK;
    }

    number2Array("2121212120", weight);
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_60(const int *account, int *weight)
{
    number2Array("0021212120", weight);
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_61(const int *account, int *weight)
{
    number2Array("2121212000", weight);
    if (8 == account[8]) {
        number2Array("2121212012", weight);
    }
    return algo01(10, weight, true, 8, account);
}

// Added by Jens Gecius, validated with one test accountID
AccountNumberCheck::Result method_62(const int *account, int *weight)
{
    number2Array("0021212000", weight);
    return algo01(10, weight, true, 8, account);
}

AccountNumberCheck::Result method_63(const int *account, int *weight)
{
    if (0 != account[0]) {
        return AccountNumberCheck::ERROR; // Added by Jens Gecius, check on invalid accountIDs
    }
    number2Array("0121212000", weight);
    if (0 == account[0] && 0 == account[1] && 0 == account[2]) {
        // shift left, add 00 as subaccount id
        int account_buf[10];
        number2Array(array2Number(account).substr(2) + "00", account_buf);
        return algo01(10, weight, true, 8, account_buf);
    } else {
        return algo01(10, weight, true, 8, account);
    }
}

AccountNumberCheck::Result method_64(const int *account, int *weight)
{
    number2Array("9058420000", weight);
    weight[1] = 10;
    return algo01(11, weight, false, 7, account);
}

AccountNumberCheck::Result method_65(const int *account, int *weight)
{
    number2Array("2121212000", weight);
    if (9 == account[8]) {
        weight[8] = 1;
        weight[9] = 2;
    }
    return algo01(10, weight, true, 8, account);
}

// Added by Jens Gecius, validated with five test accountIDs
// method 66 was changed for due-date 2014-03-03
AccountNumberCheck::Result method_66(const int *account, int *weight)
{
    if (9 == account[1]) {
        return AccountNumberCheck::OK;  // Ausnahme "method09"
    }
    if (0 != account[0]) {
        return AccountNumberCheck::ERROR;
    }
    number2Array("700654320", weight);
    int result = algo03(11, weight, false, account, 0, 9);
    if (result == 0) {
        result = 1;
    } else if (result == 1) {
        result = 0;
    } else {
        result = 11 - result;
    }
    if (account[9] == result) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_67(const int *account, int *weight)
{
    number2Array("2121212000", weight);
    return algo01(10, weight, true, 8, account);
}

AccountNumberCheck::Result method_68(const int *account, int *weight)
{
    // Modified by Jens Gecius, verified with three test accountIDs
    // size=10
    if (0 != account[0]) {
        // and digit 4 is not "9"? error
        if (9 != account[3]) {
            return AccountNumberCheck::ERROR;
        }
        number2Array("0001212120", weight);
        if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
            return AccountNumberCheck::OK;
        }
    } else { // size != 10
        // Nine digit accountIDs ranging 400000000 - 499999999 cannot be checked:
        if (4 == account[1]) {
            return AccountNumberCheck::OK;
        }
        number2Array("0121212120", weight);
        if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
            // variant 1
            return AccountNumberCheck::OK;
        } else {
            // variant 2
            number2Array("0100212120", weight);
            if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
                return AccountNumberCheck::OK;
            }
        }
    }
    return AccountNumberCheck::ERROR;
}

// Added by Jens Gecius, validated with three test accountIDs
AccountNumberCheck::Result method_69(const int *account, int *weight)
{
    int transform[6][10] =
    { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // zero for non-transform [0][x]
      {0, 1, 5, 9, 3, 7, 4, 8, 2, 6}, // first transform line   [1][x]
      {0, 1, 7, 6, 9, 8, 3, 2, 5, 4}, // second transform line  [2][x]
      {0, 1, 8, 4, 6, 2, 9, 5, 7, 3}, // third transform line   [3][x]
      {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, // fourth transform line  [4][x]
      {1, 4, 3, 2, 1, 4, 3, 2, 1, 0} }; // which transform line

    long int lastnine = atol(array2Number(account).substr(1).c_str());
    if (account[0] == 9 && lastnine >= 300000000 && lastnine <= 399999999) {
        return AccountNumberCheck::OK; // these do not get checked
    }
    if ((account[0] == 9 && (lastnine <= 700000000 || lastnine >= 799999999))
        || account[0] != 9) {
        // variant 1
        number2Array("8765432000", weight);
        if (AccountNumberCheck::OK == algo01(11, weight, false, 8, account)) {
            return AccountNumberCheck::OK;
        }
    }
    // variant 2
    return algo07(account, transform);
}

AccountNumberCheck::Result method_70(const int *account, int *weight)
{
    number2Array("4327654320", weight);
    if (5 == account[3]
        || (6 == account[3] && 9 == account[4])) {
        number2Array("0007654320", weight);
    }
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_71(const int *account, int *weight)
{
    number2Array("0654321000", weight);
    int tmp = algo03(11, weight, false, account, 0, 9);

    // no rest after division by modulus (in algo03)?
    if (0 == tmp) {
        // Changed by Jens Gecius, validated with one test accountID
        // this way we get 0 as final result
        tmp = 11;
    }
    // if 1 rest, keep it!
    if (1 == tmp) {
        tmp = 10;
    }

    // and calc the check number
    tmp = 11 - tmp;
    if (tmp == account[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_72(const int *account, int *weight)
{
    number2Array("0001212120", weight);
    return algo01(10, weight, true, 10, account);
}

// Added by Jens Gecius, validated with two test accountIDs
AccountNumberCheck::Result method_73(const int *account, int *weight)
{
    // exception "Ausnahme f. Sachkonten"
    if (9 == account[2]) {
        return method_51_exception(account, weight);
    }

    number2Array("0001212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    number2Array("0000212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    return algo01(7, weight, true, 10, account);
}

// Added by Jens Gecius, validated with one (double) test accountID
// Note: the Bundesbank-Specification-Update valid from 4.Jun.2007
//	 does not affect this method.
AccountNumberCheck::Result method_74(const int *account, int *weight)
{
    // variant 1
    int len = 10;
    number2Array("2121212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    // alternative method for 6-digit account numbers
    while (account[10-len] == 0 && len > 0) {
        len--;
    }
    if (len == 6) {
        if ((algo03a(weight, true, account, 0, 9)+5+account[9])%10 == 0) {
            return AccountNumberCheck::OK;
        }
    }
    // variant 2, extended for due date Dec 5th, 2016
    if (AccountNumberCheck::OK == method_04(account, weight)) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_75(const int *account, int *weight)
{
    // Modified by Jens Gecius
    int checkIndex;
    if ("000" == array2Number(account).substr(0, 3)) {
        checkIndex = 10;
        number2Array("0000212120", weight);
    } else if ("09" == array2Number(account).substr(0, 2)) {
        checkIndex = 8;
        number2Array("0021212000", weight);
    } else {
        checkIndex = 7;
        number2Array("0212120000", weight);
    }
    return algo01(10, weight, true, checkIndex, account);
}

AccountNumberCheck::Result method_76(const int *account, int *weight)
{
    // Modified by Jens Gecius, validated with four test accountIDs
    number2Array("0765432000", weight);
    int tmp = algo03(11, weight, false, account, 0, 6);

    if (tmp == account[7] && (account[0] == 0 || account[0] == 4 || account[0] > 5)) {
        return AccountNumberCheck::OK;
    } else if (account[0] == 0 && account[1] == 0) {
        // shift left if two lefts are 0, add 00 as subaccount id and try again
        int account_buf[10];
        number2Array(array2Number(account).substr(2) + "00", account_buf);
        tmp = algo03(11, weight, false, account_buf, 0, 6);
        if (tmp == account_buf[7]
            && (account_buf[0] == 0 || account_buf[0] == 4 || account_buf[0] > 5)) {
            return AccountNumberCheck::OK;
        }
    }
    return AccountNumberCheck::ERROR;
}

// Added by Jens Gecius, validated with four test accountIDs
AccountNumberCheck::Result method_77(const int *account, int *weight)
{
    number2Array("0000054321", weight);
    if (0 == algo03(11, weight, false, account, 0, 9)) {
        return AccountNumberCheck::OK;
    }
    weight[8] = 4;
    weight[9] = 5;
    if (0 == algo03(11, weight, false, account, 0, 9)) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_78(const int *account, int *weight)
{
    if (0 == account[0] && 0 == account[1]) {
        return AccountNumberCheck::OK;
    }

    number2Array("2121212120", weight);
    return algo01(10, weight, true, 10, account);
}

AccountNumberCheck::Result method_79(const int *account, int *weight)
{
    // Modified by Jens Gecius, not verified as no bank seems to use it...
    if (0 == account[0]) {
        return AccountNumberCheck::ERROR;
    }
    int checkIndex = 10;

    if (2 < account[0] && 9 > account[0]) {
        number2Array("2121212120", weight);
    } else {
        checkIndex--;
        number2Array("1212121200", weight);
    }

    return algo01(10, weight, true, checkIndex, account);
}

AccountNumberCheck::Result method_80(const int *account, int *weight)
{
    // exception "Ausnahme f. Sachkonten"
    if (9 == account[2]) {
        return method_51_exception(account, weight);
    }

    // var 1
    number2Array("0000212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // var 2:
    return algo01(7, weight, true, 10, account);
}

AccountNumberCheck::Result method_81(const int *account, int *weight)
{
    // exception "Ausnahme f. Sachkonten"
    if (9 == account[2]) {
        return method_51_exception(account, weight);
    }

    number2Array("0007654320", weight);
    weight[0] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_82(const int *account, int *weight)
{
    if (9 == account[2] && 9 == account[3]) {
        number2Array("987654320", weight);
        weight[0] = 10;
        return algo01(11, weight, false, 10, account);
    } else {
        number2Array("0000654320", weight);
        return algo01(11, weight, false, 10, account);
    }
}

AccountNumberCheck::Result method_83(const int *account, int *weight)
{
    // var a:
    number2Array("0007654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // var b:
    number2Array("0000654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // var c:
    if (account[9] > 6) {
        return AccountNumberCheck::ERROR;
    }
    if (AccountNumberCheck::OK == algo01(7, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // non-customer accounts
    if (9 != account[2] || 9 != account[3]) {
        return AccountNumberCheck::ERROR;
    }

    number2Array("0087654320", weight);
    return algo01(11, weight, false, 10, account);
}

// method 84 was extended for due-date 2013-06-03
AccountNumberCheck::Result method_84(const int *account, int *weight)
{
    // exception "Ausnahme f. Sachkonten"
    if (9 == account[2]) {
        return method_51_exception(account, weight);
    }

    // Methode A
    number2Array("0000654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // Methode B
    if (AccountNumberCheck::OK == algo01(7, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // Methode C
    number2Array("0000212120", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_85(const int *account, int *weight)
{
    // exception: (method "02" using modified weight)
    if (9 == account[2] && 9 == account[3]) {
        number2Array("0087654320", weight);
        return algo02(11, weight, 10, account, 2, 8);
    }

    // var a:
    number2Array("0007654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // var b:
    number2Array("0000654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // var c:
    if (account[9] > 6) {
        return AccountNumberCheck::ERROR;
    }

    number2Array("0000654320", weight);
    return algo01(7, weight, false, 10, account);
}

AccountNumberCheck::Result method_86(const int *account, int *weight)
{
    // exception "Ausnahme f. Sachkonten"
    if (9 == account[2]) {
        return method_51_exception(account, weight);
    }

    // var 1
    number2Array("0001212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // var2: on error try with 32
    number2Array("0007654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_87(const int *account, int *weight)
{
    // Modified by Jens Gecius, algo changed September 6th, 2004
    // Checked with (positive only) Bundesbank-Testnumbers
    if (9 == account[2]) {
        return method_51_exception(account, weight); // exception "Ausnahme f. Sachkonten"
    }
    // method a, b, c not verified in regard of changes (Sep 6th, 2004)!

    // method a
    if (AccountNumberCheck::OK == algo06(account)) {
        return AccountNumberCheck::OK;
    }

    // method b
    number2Array("0000654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // method c
    if (AccountNumberCheck::OK == algo01(7, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // method d, extended for due date Sep 7th, 2015
    number2Array("0007654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_88(const int *account, int *weight)
{
    number2Array("0007654320", weight);
    if (9 == account[2]) {
        number2Array("0087654320", weight);
    }
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_89(const int *account, int *weight)
{
    // some numbers can not be checked
    std::string acc10 = array2Number(account);
    if (acc10 < "0000999999" || 0 != account[0]) {
        return AccountNumberCheck::OK;
    }

    // those with length 7
    if (0 == account[0] && 0 == account[1] && 0 == account[2]) {
        number2Array("0007654320", weight);
        return algo01(11, weight, true, 10, account);
    }

    // length 8 or 9? check with method 10
    number2Array("987654320", weight);
    weight[0] = 10;
    return algo01(11, weight, false, 10, account);
}

// method 90 was changed for due-date 2014-09-08
AccountNumberCheck::Result method_90(const int *account, int *weight)
{
    // variant a
    number2Array("0007654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // variant b
    number2Array("0000654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // variant c
    if (AccountNumberCheck::OK == algo01(07, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // variant d
    if (AccountNumberCheck::OK == algo01(9, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // variant e
    number2Array("0000212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // Methode G
    number2Array("0001212120", weight);
    if (AccountNumberCheck::OK == algo01(7, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // non-customer-accounts
    number2Array("0087654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_91(const int *account, int *weight)
{
    number2Array("7654320000", weight);
    AccountNumberCheck::Result tmp = algo01(11, weight, false, 7, account);
    if (AccountNumberCheck::OK == tmp) {
        return AccountNumberCheck::OK;
    } else {
        number2Array("2345670000", weight);
        tmp = algo01(11, weight, false, 7, account);
        if (AccountNumberCheck::OK == tmp) {
            return AccountNumberCheck::OK;
        } else {
            number2Array("0987650432", weight);
            weight[0] = 10;
            tmp = algo01(11, weight, false, 7, account);
            if (AccountNumberCheck::OK == tmp) {
                return AccountNumberCheck::OK;
            } else {
                number2Array("9058420000", weight);
                weight[1] = 10;
                return algo01(11, weight, false, 7, account);
            }
        }
    }
}

AccountNumberCheck::Result method_92(const int *account, int *weight)
{
    number2Array("0001731730", weight);
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_93(const int *account, int *weight)
{
    // Modified by Jens Gecius, indirectly validated via method A4,
    // as no bank seems to use it...
    int checkIndex = 6;
    number2Array("6543200000", weight);
    if ("0000" == array2Number(account).substr(0, 4)) {
        checkIndex = 10;
        number2Array("0000654320", weight);
    }

    if (AccountNumberCheck::OK == algo01(11, weight, false, checkIndex, account)) {
        return AccountNumberCheck::OK;
    }
    int result = algo03(7, weight, false, account, 0, 9);
    if (result == 0) {
        result = 7;
    }
    if (account[checkIndex - 1] == (7 - result)) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_94(const int *account, int *weight)
{
    number2Array("1212121210", weight);
    return algo01(10, weight, true, 10, account);
}

// method 95 was changed for due-date 09.09.2013
AccountNumberCheck::Result method_95(const int *account, int *weight)
{
    // some numbers do not get checked
    std::string accNumber = array2Number(account);
    if (("0000000001" <= accNumber && accNumber <= "0001999999")
        || ("0009000000" <= accNumber && accNumber <= "0025999999")
        || ("0396000000" <= accNumber && accNumber <= "0499999999")
        || ("0700000000" <= accNumber && accNumber <= "0799999999")
        || ("0910000000" <= accNumber && accNumber <= "0989999999")) {
        return AccountNumberCheck::OK;
    }

    number2Array("4327654320", weight);

    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_96(const int *account, int *weight)
{
    // Modified by Jens Gecius
    number2Array("1987654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }
    // check with 00
    number2Array("2121212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    std::string acc10 = array2Number(account);
    if (acc10 > "0001300000" && acc10 < "0099399999") {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_97(const int *account, int *weight)
{
    std::string tmp = array2Number(account).substr(0, 9);
    long_long valueX = number2LongLong(tmp);
    valueX -= (valueX / 11) * 11;
    valueX = valueX % 10;

    if (valueX == account[9]) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

AccountNumberCheck::Result method_98(const int *account, int *weight)
{
    number2Array("0037137130", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, false, 10, account)) {
        return AccountNumberCheck::OK;
    }

    // on error run method 32
    number2Array("0007654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_99(const int *account, int *weight)
{
    // some numbers do not get checked
    if ("0396000000" <= array2Number(account)
        && array2Number(account) <= "0499999999") {
        return AccountNumberCheck::OK;
    }
    number2Array("4327654320", weight);
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_A0(const int *account, int *weight)
{
    // some numbers are not checked
    if ("0000000" == array2Number(account).substr(0, 7)) {
        return AccountNumberCheck::OK;
    }
    // Modified by Jens Gecius, NOT validated as no bank seems to use it
    // fixed by Alexander Kurz 2006-05-17, validated with published numbers
    number2Array("0000058420", weight);
    weight[4] = 10;
    int result = algo03a(weight, false, account, 0, 9);
    result = result % 11;
    if (result == 0 || result == 1) {
        result = 0;
    } else {
        result = 11 - result;
    }
    if (account[9] == result) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_A1(const int *account, int *weight)
{
    // Modified by Jens Gecius as of recent changes, validated with six test accountIDs
    // three positives and three negatives (first algo to check negatives)
    std::string acc10 = array2Number(account);
    if ((acc10 < "1000000000" && acc10 > "0099999999")
        || acc10 < "0010000000") {
        return AccountNumberCheck::ERROR;
    }
    number2Array("0021212120", weight);
    return algo01(10, weight, true, 10, account);
}

// Added by Jens Gecius, validated with six test accountIDs (4 positives, 2 negatives)
AccountNumberCheck::Result method_A2(const int *account, int *weight)
{
    number2Array("2121212120", weight);     // variant 1
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    return method_04(account, weight);       // variant 2
}

// Added by Jens Gecius, NOT validated as no bank seems to use it...
AccountNumberCheck::Result method_A3(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    number2Array("0987654320", weight);
    weight[0] = 10;
    return algo01(11, weight, false, 10, account);
}

// Added by Jens Gecius, validated with 16 test accountIDs (11 pos
// and 5 negs). The test accountIDs chosen in the Bundesbank paper
// are stupid, as some of the false ones are actually correct as of
// other variants also relevant for them!!!  costed me another hour
// calculating all of them by hand! grr.
AccountNumberCheck::Result method_A4(const int *account, int *weight)
{
    number2Array("0000654320", weight);
    if (account[2] == 9 && account[3] == 9) { // variant 3
        if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
            return AccountNumberCheck::OK;
        }
    } else {
        number2Array("0007654320", weight);
        if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) { // variant 1
            return AccountNumberCheck::OK;
        }
        int result = algo03(7, weight, false, account, 0, 9); // variant 2
        if (result == 0) {
            result = 7;
        }
        if (account[9] == (7 - result)) {
            return AccountNumberCheck::OK;
        }
    }
    int checkIndex = 6;     // variant 4
    number2Array("6543200000", weight);
    if ("0000" == array2Number(account).substr(0, 4)) {
        checkIndex = 10;
        number2Array("0000654320", weight);
    }

    if (AccountNumberCheck::OK == algo01(11, weight, false, checkIndex, account)) {
        return AccountNumberCheck::OK;
    }
    int result = algo03(7, weight, false, account, 0, 9);
    if (result == 0) {
        result = 7;
    }
    if (account[checkIndex - 1] == (7 - result)) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// Added by Jens Gecius, NOT validated as no bank seems to use it...
AccountNumberCheck::Result method_A5(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    if (account[0] == 9) {
        return AccountNumberCheck::ERROR;
    }
    number2Array("0987654320", weight);
    weight[0] = 10;
    return algo01(11, weight, false, 10, account);
}

AccountNumberCheck::Result method_A6(const int *account, int *weight)
{
    if (account[1] == 8) {
        number2Array("2121212120", weight);
        return algo01(10, weight, true, 10, account);
    } else {
        number2Array("1731731730", weight);
        return algo01(10, weight, false, 10, account);
    }
}

AccountNumberCheck::Result method_A7(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, true, 10, account)) {
        return AccountNumberCheck::OK;
    }
    return algo01(10, weight, false, 10, account);
}

AccountNumberCheck::Result method_A8(const int *account, int *weight)
{
    // revised method A8 according to the description published in March 7 2005
    // tested with testnumbers for method A8 and exception/51
    if (9 == account[2]) {
        return method_51_exception(account, weight); // exception "Ausnahme f. Sachkonten"
    }
    number2Array("0007654320", weight);
    if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
        return AccountNumberCheck::OK;      // variant 1: weight modified method 06
    }
    number2Array("0001212120", weight);
    return algo01(10, weight, true, 10, account);   // variant 2: weight modified method 00
}

AccountNumberCheck::Result method_A9(const int *account, int *weight)
{
    number2Array("1731731730", weight);
    if (algo01(10, weight, false, 10, account) != AccountNumberCheck::OK) {
        number2Array("4327654320", weight);
        return algo01(11, weight, false, 10, account);
    }
    return AccountNumberCheck::OK;
}

// Added by Jens Gecius (new Method as of December 6th, 2004)
// Not checked, no bank seems to use it.
AccountNumberCheck::Result method_B0(const int *account, int *weight)
{
    if (array2Number(account) < "1000000000" || account[0] == 8) {
        return AccountNumberCheck::ERROR;
    }
    if (account[7] == 1 || account[7] == 2 || account[7] == 3 || account[7] == 6) {
        return AccountNumberCheck::OK; // variant 1 -> no check if 1,2,3 or 6 at 8th place of account (method "09")
    }
    // Other accounts: method "06"
    number2Array("4327654320", weight);
    return algo01(11, weight, false, 10, account);
}

// Added by Jens Gecius (new Method as of September 6th, 2004)
// Checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_B1(const int *account, int *weight)
{
    number2Array("1371371370", weight);
    if (AccountNumberCheck::OK == algo01(10, weight, false, 10, account)) {
        return AccountNumberCheck::OK; // variant 1 (method "05")
    }
    number2Array("1731731730", weight);
    return algo01(10, weight, false, 10, account);
    // variant 2 (method "01")
}

// Added by Jens Gecius (new Method as of September 6th, 2004)
AccountNumberCheck::Result method_B2(const int *account, int *weight)
{
    if (account[0] < 8) {
        return method_02(account, weight); // variant 1
    } // variant 1 (method "02")
    if (account[0] == 8 || account[0] == 9) {
        return method_00(account, weight); // variant 2
    } // variant 2 (method "00")
    return AccountNumberCheck::ERROR; // should never happen, to be on the safe side
}

// Added by Jens Gecius (new method as of December 6th, 2004)
// Checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_B3(const int *account, int *weight)
{
    if (account[0] < 9) {
        number2Array("0007654320", weight);
        return algo01(11, weight, false, 10, account);
    } // variant 1 (method "32")
    if (account[0] == 9) {
        number2Array("4327654320", weight);
        return algo01(11, weight, false, 10, account);
    } // variant 2 (method "06")
    return AccountNumberCheck::ERROR; // should never happen, to be on the safe side
}

// B4 and B5 Added by Alexander Kurz
// new method as of March 7th, 2005, checked with Bundesbank-Testnumbers
// note: this is an implementation of method B4 according to the
//       corrected description published in zv_pz200503II.pdf
AccountNumberCheck::Result method_B4(const int *account, int *weight)
{
    if (account[0] == 9) {
        return method_00(account, weight); // variant 1
    }
    if (account[0] < 9) {
        number2Array("0987654320", weight);
        weight[0] = 10;
        return algo02(11, weight, 10, account, 0, 8);
    } // variant 2 (method "02" using modified weight)
    return AccountNumberCheck::ERROR; // should never happen, to be on the safe side
}

// new method B5 as of June 6th, 2005, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_B5(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_05(account, weight)) {
        return AccountNumberCheck::OK;  // variant 1
    }
    if (account[0] == 8 || account[0] == 9) {
        return AccountNumberCheck::ERROR;
    }
    return method_00(account, weight);       // variant 2
}

// B6, B7 and B8 Added by Alexander Kurz
// new method as of September 5th, 2005, checked with Bundesbank-Testnumbers
// method B6 was last changed for due-date September, 5 2011
AccountNumberCheck::Result method_B6(const int *account, int *weight, const std::string &accountId,
                                     const std::string &bankId)
{
    if (account[0] > 0 && account[0] <= 9) {
        return method_20(account, weight); // variant 1
    }
    if (account[0] == 0 && account[1] == 2 && account[2] == 6
        && account[3] == 9 && (account[4] > 0 || account[4] <= 9)) {
        return method_20(account, weight); // variant 1
    }
    if (account[0] == 0) {
        return method_53(account, weight, accountId, bankId); // variant 2
    }
    return AccountNumberCheck::ERROR; // should never happen, to be on the safe side
}

// new method as of September 5th, 2005, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_B7(const int *account, int *weight)
{
    std::string accNumber = array2Number(account);
    if (("0001000000" <= accNumber && accNumber <= "0005999999")
        || ("0700000000" <= accNumber && accNumber <= "0899999999")) {
        return method_01(account, weight); // variant 1
    } else {
        return AccountNumberCheck::OK;  // variant 2, "method 9" :-))
    }
}

// method B8 was last changed for due-date June, 6 2011
AccountNumberCheck::Result method_B8(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_20(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    if (AccountNumberCheck::OK == method_29(account, weight)) { // variant 2
        return AccountNumberCheck::OK;
    }
    if (account[0] == 5 && account[1] > 0 && account[1] <= 9) { // variant 3
        return AccountNumberCheck::OK;
    }
    if (account[0] == 9
        && ((account[1] == 0 && account[2] > 0 && account[2] <= 9)
            || (account[1] == 1 && account[2] == 0))) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// B9 and C0 added by Alexander Kurz
// new method as of December 5th, 2005, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_B9(const int *account, int *weight)
{
    if (account[0] == 0 && account[1] == 0 && account[2] > 0) {
        number2Array("0012312310", weight); // variant 1
        int result = algo05(11, 10, weight, account, 2, 8);
        if (result == account[9]) {
            return AccountNumberCheck::OK;
        }
        result += result < 5 ? 5 : -5;
        if (result == account[9]) {
            return AccountNumberCheck::OK;
        }
    } else if (account[0] == 0 && account[1] == 0 && account[2] == 0 && account[3] > 0) {
        number2Array("0006543210", weight); // variant 2
        int result = algo03(11, weight, false, account, 3, 8);
        if (result == account[9]) {
            return AccountNumberCheck::OK;
        }
        result += result < 5 ? 5 : -5;
        if (result == account[9]) {
            return AccountNumberCheck::OK;
        }
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_C0(const int *account, int *weight, const std::string &accountId,
                                     const std::string &bankId)
{
    if (account[0] == 0 && account[1] == 0 && account[2] > 0) {
        if (AccountNumberCheck::OK == method_52(account, weight, accountId, bankId)) { // variant 1
            return AccountNumberCheck::OK;
        }
    }
    return method_20(account, weight);   // variant 2
}

// new method C1 and C2 as of June 5th, 2006, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_C1(const int *account, int *weight)
{
    if (account[0] != 5) {
        return method_17(account, weight);     // variant 1
    }
    // variant 2 is a modified version of method_17
    number2Array("1212121210", weight);
    int tmp = algo03a(weight, true, account, 0, 9);
    tmp = (tmp - 1) % 11;
    tmp = 10 - tmp;
    if (10 == tmp) {
        tmp = 0;
    }
    if (account[9] == tmp) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

AccountNumberCheck::Result method_C2(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_22(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    return method_00(account, weight);   // variant 2
}

// new method C3 and C4 valid from March 5th, 2007, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_C3(const int *account, int *weight)
{
    if (account[0] != 9) {
        return method_00(account, weight);  // variant 1
    } else {
        return method_58(account, weight); // variant 2
    }
}

AccountNumberCheck::Result method_C4(const int *account, int *weight)
{
    if (account[0] != 9) {
        return method_15(account, weight);  // variant 1
    } else {
        return method_58(account, weight); // variant 2
    }
}

// new method C5 valid from September 3rd, 2007, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_C5(const int *account, int *weight)
{
    int len = 10;
    while (account[10-len] == 0 && len > 0) {
        len--;
    }

    if ((len == 6 && account[4] >= 1 && account[4] <= 8)
        || (len == 9 && account[1] >= 1 && account[1] <= 8)) {
        return method_75(account, weight);  // variant 1
    }
    if (len == 8 && account[2] >= 3 && account[2] <= 5) {
        return AccountNumberCheck::OK;  // vatiant 4a / "method09"
    }
    if (len == 10) {
        switch (account[0]) {
        case 1:
        case 4:
        case 5:
        case 6:
        case 9:
            return method_29(account, weight);   // variant 2
        case 3:
            return method_00(account, weight);   // variant 3
        case 7:
            if (account[1] == 0) {
                return AccountNumberCheck::OK;                      // vatiant 4b / "method09"
            }
            break;
        case 8:
            if (account[1] == 5) {
                return AccountNumberCheck::OK;                      // vatiant 4c / "method09"
            }
            break;
        default:
            break;
        }
    }
    return AccountNumberCheck::ERROR;
}

// method C6 was last changed for due-date March, 4 2013
// checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_C6(const int *account, int *weight)
{
    number2Array("0121212120", weight);
    // quick hack: the processed number-prefix boils down to a constant factor:
    // e.g. for prefix="5499570" -> factor=q(2*5)+q(4)+q(2*9)+q(9)+q(2*5)+q(7)+q(0)=1+4+9+9+1+7+0=31
    int mod_factor = 0;
    switch (account[0]) {
    case 0:
        mod_factor = 30;
        break;                      // prefix="4451970"
    case 1:
        mod_factor = 33;
        break;                      // prefix="4451981"
    case 2:
        mod_factor = 36;
        break;                      // prefix="4451992"
    case 3:
        mod_factor = 38;
        break;                      // prefix="4451993"
    case 4:
        mod_factor = 45;
        break;                      // prefix="4344992"
    case 5:
        mod_factor = 41;
        break;                      // prefix="4344990"
    case 6:
        mod_factor = 43;
        break;                      // prefix="4344991"
    case 7:
        mod_factor = 31;
        break;                      // prefix="5499570"
    case 8:
        mod_factor = 40;
        break;                      // prefix="4451994"
    case 9:
        mod_factor = 40;
        break;                      // prefix="5499579"
    default:
        return AccountNumberCheck::ERROR;
    }
    int result = algo03(10, weight, true, account, 1, 8);
    result += mod_factor;
    // calc the check number, note: 1000 should be large enough.
    result = (1000 - result) % 10;
    // compare the result with the real check number
    if (account[9] == result) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

// new method as of December 3rd, 2007, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_C7(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_63(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    return method_06(account, weight);               // variant 2
}

// new methods C8 and C9 valid from June 6th, 2008, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_C8(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_00(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    if (AccountNumberCheck::OK == method_04(account, weight)) { // variant 2
        return AccountNumberCheck::OK;
    }
    return method_07(account, weight);               // variant 3
}

AccountNumberCheck::Result method_C9(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_00(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    return method_07(account, weight);               // variant 2
}

// new methods D0 and D1 valid from September 8th, 2008, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D0(const int *account, int *weight)
{
    if (account[0] != 5 || account[1] != 7) {
        return method_20(account, weight);      // variant 1
    } else {
        return AccountNumberCheck::OK;          // variant 2, "method 9" again :-))
    }
}

// method D1 was modified with due date starting from 7. June 2010
// method D1 was last modified for due date 2013-03-04
AccountNumberCheck::Result method_D1(const int *account, int *weight)
{
    if (account[0] == 8) {
        return AccountNumberCheck::ERROR;
    }
    // note: this method is quite similar to method_C6
    number2Array("2121212120", weight);
    int result = algo03(10, weight, true, account, 0, 8);
    // quick hack: the processed number-prefix "436338" boils
    //		   down to a constant factor
    result += 31;   // prefix "436338" -> factor 31
    // calc the check number, note: 1000 should be large enough.
    result = (1000 - result) % 10;
    // compare the result with the real check number
    if (account[9] == result) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

// new methods D2 and D3 valid from December 8th, 2008
AccountNumberCheck::Result method_D2(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_95(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    if (AccountNumberCheck::OK == method_00(account, weight)) { // variant 2
        return AccountNumberCheck::OK;
    }
    return method_68(account, weight);               // variant 3
}

AccountNumberCheck::Result method_D3(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_00(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    return method_27(account, weight);               // variant 2
}

// method D4 was last changed for due-date June, 6 2011
// checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D4(const int *account, int *weight)
{
    // note this is a slightly modified version of the old method D1
    if (account[0] == 0) {
        return AccountNumberCheck::ERROR;
    }
    // note: from here on this method is quite similar to method_C6
    number2Array("2121212120", weight);
    int result = algo03(10, weight, true, account, 0, 8);
    // quick hack: the processed leading numbers "428259" boil down to a constant factor of 29
    result += 29;
    // calc the check number, note: 1000 should be large enough.
    result = (1000 - result) % 10;
    // compare the result with the real check number
    if (account[9] == result) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

// new method D5 valid from December 6th, 2010, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D5(const int *account, int *weight)
{
    if (account[2] == 9 && account[3] == 9) {
        // variant 1: like method_06, but with different weight
        number2Array("0087654320", weight);
        return algo01(11, weight, false, 10, account);
    } else {
        number2Array("0007654320", weight);
        // variant 2: like method_06, but with different weight
        if (AccountNumberCheck::OK == algo01(11, weight, false, 10, account)) {
            return AccountNumberCheck::OK;
        }
        // variant 3
        if (AccountNumberCheck::OK == algo02(7, weight, 10, account, 3, 8)) {
            return AccountNumberCheck::OK;
        }
        // variant 4
        return algo02(10, weight, 10, account, 3, 8);
    }
}

// new method D6 valid from March 6th, 2011, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D6(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_07(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    if (AccountNumberCheck::OK == method_03(account, weight)) { // variant 2
        return AccountNumberCheck::OK;
    }
    return method_00(account, weight);   // variant 3
}

// new method D7 valid from March 6th, 2011, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D7(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    int tmp = algo03(10, weight, true, account, 0, 9);
    if (tmp == account[9]) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

// new method D8 valid from March 6th, 2011, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D8(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    if (account[0] > 0 && account[0] <= 9) { // variant 1
        return algo01(10, weight, true, 10, account);
    }
    if (account[0] == 0 && account[1] == 0
        && account[2] > 0 && account[2] <= 9) { // variant 2
        return AccountNumberCheck::OK;  // "method09"
    }
    return AccountNumberCheck::ERROR;
}

// new method D9 valid from June 4th, 2012, checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_D9(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_00(account, weight)) { // variant 1
        return AccountNumberCheck::OK;
    }
    if (AccountNumberCheck::OK == method_10(account, weight)) { // variant 2
        return AccountNumberCheck::OK;
    }
    return method_18(account, weight);   // variant 3
}

// new method E0 valid from June 3rd, 2013, checked with Bundesbank-Testnumbers
// note similarities to method_C1/Variant2 and method_17
AccountNumberCheck::Result method_E0(const int *account, int *weight)
{
    number2Array("2121212120", weight);
    int tmp = algo03a(weight, true, account, 0, 9);
    tmp = (tmp + 7) % 10;
    tmp = 10 - tmp;
    if (10 == tmp) {
        tmp = 0;
    }
    if (tmp == account[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// new method E1 valid from 2013-12-09
AccountNumberCheck::Result method_E1(const int *account, int *weight)
{
    int account_e1[10];
    int i;
    for (i = 0; i < 9; i++) {
        account_e1[i] = 48 + account[i]; // Umwandlung exklusiv Pruefziffer
    }
    account_e1[9] = account[9];
    number2Array("9:;6543210", weight);  // bad Hack: ASCII-Conversation ':' -> 10, ';' -> 11
    int tmp = algo03(11, weight, false, account_e1, 0, 9);
    if (10 == tmp) {
        return AccountNumberCheck::ERROR;
    }
    if (tmp == account[9]) {
        return AccountNumberCheck::OK;
    }
    return AccountNumberCheck::ERROR;
}

// new method E2 valid from June 8th, 2015
// checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_E2(const int *account, int *weight)
{
    // note this is a slightly modified version of method_D1
    // accountIDs starting with 6, 7, 8, or 9 are errors
    if (account[0] > 5) {
        return AccountNumberCheck::ERROR;
    }
    // note: from here on this method is quite similar to method_C6
    number2Array("2121212120", weight);
    int result = algo03(10, weight, true, account, 0, 8);
    // quick hack: the processed leading numbers "438320" boil down to a constant factor of 25
    result += 25;
    // calc the check number, note: 1000 should be large enough.
    result = (1000 - result) % 10;
    // compare the result with the real check number
    if (account[9] == result) {
        return AccountNumberCheck::OK;
    } else {
        return AccountNumberCheck::ERROR;
    }
}

// new method E3 valid from March 6th, 2017
// checked with Bundesbank-Testnumbers
AccountNumberCheck::Result method_E3(const int *account, int *weight)
{
    if (AccountNumberCheck::OK == method_00(account, weight)) {  // variant 1
        return AccountNumberCheck::OK;
    }
    return method_21(account, weight);               // variant 2
}

struct method_func_s {
    const char *str;
    AccountNumberCheck::MethodFunc func;
};
const struct method_func_s cb_funcs[] = {
    {
        "00", method_00
    },
    { "01", method_01},
    { "02", method_02},
    { "03", method_03},
    { "04", method_04},
    { "05", method_05},
    { "06", method_06},
    { "07", method_07},
    { "08", method_08},
    { "09", method_09},
    { "10", method_10},
    { "11", method_11},
    { "12", method_12},
    { "13", method_13},
    { "14", method_14},
    { "15", method_15},
    { "16", method_16},
    { "17", method_17},
    { "18", method_18},
    { "19", method_19},
    { "20", method_20},
    { "21", method_21},
    { "22", method_22},
    { "23", method_23},
    { "24", method_24},
    { "25", method_25},
    { "26", method_26},
    { "27", method_27},
    { "28", method_28},
    { "29", method_29},
    { "30", method_30},
    { "31", method_31},
    { "32", method_32},
    { "33", method_33},
    { "34", method_34},
    { "35", method_35},
    { "36", method_36},
    { "37", method_37},
    { "38", method_38},
    { "39", method_39},
    { "40", method_40},
    { "41", method_41},
    { "42", method_42},
    { "43", method_43},
    { "44", method_44},
    { "45", method_45},
    { "46", method_46},
    { "47", method_47},
    { "48", method_48},
    { "49", method_49},
    { "50", method_50},
    { "51", method_51},
    { "54", method_54},
    { "55", method_55},
    { "56", method_56},
    { "57", method_57},
    { "58", method_58},
    { "59", method_59},
    { "60", method_60},
    { "61", method_61},
    { "62", method_62},
    { "63", method_63},
    { "64", method_64},
    { "65", method_65},
    { "66", method_66},
    { "67", method_67},
    { "68", method_68},
    { "69", method_69},
    { "70", method_70},
    { "71", method_71},
    { "72", method_72},
    { "74", method_74},
    { "73", method_73},
    { "75", method_75},
    { "76", method_76},
    { "77", method_77},
    { "78", method_78},
    { "79", method_79},
    { "80", method_80},
    { "81", method_81},
    { "82", method_82},
    { "83", method_83},
    { "84", method_84},
    { "85", method_85},
    { "86", method_86},
    { "87", method_87},
    { "88", method_88},
    { "89", method_89},
    { "90", method_90},
    { "91", method_91},
    { "92", method_92},
    { "93", method_93},
    { "94", method_94},
    { "95", method_95},
    { "96", method_96},
    { "97", method_97},
    { "98", method_98},
    { "99", method_99},
    { "A0", method_A0},
    { "A1", method_A1},
    { "A2", method_A2},
    { "A3", method_A3},
    { "A4", method_A4},
    { "A5", method_A5},
    { "A6", method_A6},
    { "A7", method_A7},
    { "A8", method_A8},
    { "A9", method_A9},
    { "B0", method_B0},
    { "B1", method_B1},
    { "B2", method_B2},
    { "B3", method_B3},
    { "B4", method_B4},
    { "B5", method_B5},
    { "B7", method_B7},
    { "B8", method_B8},
    { "B9", method_B9},
    { "C1", method_C1},
    { "C2", method_C2},
    { "C3", method_C3},
    { "C4", method_C4},
    { "C5", method_C5},
    { "C6", method_C6},
    { "C7", method_C7},
    { "C8", method_C8},
    { "C9", method_C9},
    { "D0", method_D0},
    { "D1", method_D1},
    { "D2", method_D2},
    { "D3", method_D3},
    { "D4", method_D4},
    { "D5", method_D5},
    { "D6", method_D6},
    { "D7", method_D7},
    { "D8", method_D8},
    { "D9", method_D9},
    { "E0", method_E0},
    { "E1", method_E1},
    { "E2", method_E2},
    { "E3", method_E3},
    { 0, 0} // Important: The array has to end with the {0,0} entry,
    // otherwise initMethodMap() will runaway and crash!
};

// This second structure and array is only a quick workaround for
// those method functions which use the account and bankId
// string. Since 95% of all methods don't use them, I decided against
// using the MethodFuncLong prototype for all methods. Maybe in the
// future, these five methods will also switch to the MethodFunc
// prototype i.e. do not use the accountId and bankId
// string. Whatever, for now this works quite well.
struct method_funcLong_s {
    const char *str;
    AccountNumberCheck::MethodFuncLong func;
};
const struct method_funcLong_s cb_funcs_long[] = {
    {
        "52", method_52
    },
    { "53", method_53},
    { "B6", method_B6},
    { "C0", method_C0},
    { 0, 0} // Important: The array has to end with the {0,0} entry,
            // otherwise initMethodMap() will runaway and crash!
};

void AccountNumberCheck::initMethodMap()
{
    const struct method_func_s *ptr = cb_funcs;
    for (; ptr->str != 0; ptr++) {
        // Insertion list is sorted alphabetically
        method_map.insert(method_map.end(),
                          method_map_t::value_type(ptr->str, ptr->func));
    }

    const struct method_funcLong_s *ptr2 = cb_funcs_long;
    for (; ptr2->str != 0; ptr2++) {
        // Insertion list is sorted alphabetically
        method_map2.insert(method_map2.end(),
                           method_map2_t::value_type(ptr2->str, ptr2->func));
    }
}
