/**
   * metodo che stampa la classifica su pdf
   *
   * @param ranks lista di coppie (squadra, punteggio)
   * @param isConcluse flag vero se la classifica � definitiva
   * @param doc documento pdf su cui stampare
   * @throws DocumentException sollevata quando si verificano errori di stampa su pdf
   */
  private void printRanking(List<Pair<TeamEntity, Integer>> ranks, Boolean isConcluse, Document doc)
      throws DocumentException {
    // tabella pdf, 3 colonne
    PdfPTable table = new PdfPTable(3);
    // cella
    PdfPCell cell;
    // aggiungi le celle di intestazione
    table.setHeaderRows(1);
    table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
    table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
    table.setWidthPercentage(100);
    table.setWidths(new float[] {0.2f, 1, 0.2f});
    table.addCell("Posizione");
    table.addCell("Squadra");
    table.addCell("Punteggio");

    Integer position = 0;
    Integer oldPoints = Integer.MAX_VALUE;
    Integer newPoints;
    for (Iterator<Pair<TeamEntity, Integer>> it = ranks.iterator(); it.hasNext(); ) {
      Pair<TeamEntity, Integer> coppia = it.next();
      newPoints = coppia.getSecond();
      // se non � un parimerito avanza di posizione
      if (newPoints < oldPoints) {
        oldPoints = newPoints;
        position++;
      }
      // stampa la posizione
      table.addCell(position.toString());
      // stampa il nome della squadra
      cell = new PdfPCell(new Phrase(coppia.getFirst().getName()));
      cell.setHorizontalAlignment(Element.ALIGN_LEFT);
      table.addCell(cell);
      // stampa il punteggio
      table.addCell(newPoints.toString());
    }

    // aggiungi il titolo al pdf
    doc.add(
        new Phrase(
            new Chunk(
                "\nClassifica " + (isConcluse ? "definitiva" : "provvisoria"),
                FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD))));
    // aggiungi la tabella al pdf
    doc.add(table);
  }
 public ImageRecord[] calculateOutputs(ImageRecord[] inputs) throws ScaleNotMatchException {
   this.inputs = inputs;
   for (int i = 0; i < outMapSize; i++) {
     Double[][] z =
         new Double[outputSize.GetLeftElement()][outputSize.GetRightElement()]; // 初始化输出图像
     for (int j = 0; j < inputs.length; j++) {
       ImageRecord input = inputs[j];
       z =
           MathUtils.addArrays(
               z, MathUtils.conv(input.getImage(), kernels[j][i].getKernel(), "valid")); // 图像卷积
     }
     z = MathUtils.AddConstantToArray(z, b[i]);
     z = MathUtils.SigmoidForImage(z);
     outputs[i] = new ImageRecord(z, -999);
   }
   return outputs;
 }
  public ImageRecord[] update(ImageRecord[] deltas, Integer batchSize, Double learningRate)
      throws ScaleNotMatchException {
    int imageSize = deltas.length;
    ImageRecord[] deltaResult = new ImageRecord[this.inMapSize];
    for (int i = 0; i < imageSize; i++)
      deltas[i] =
          new ImageRecord(
              MathUtils.MatrixElementMultiply(
                  deltas[i].getImage(),
                  MathUtils.MatrixElementMultiply(
                      outputs[i].getImage(),
                      MathUtils.ContantMinusArray(outputs[i].getImage(), 1.0))),
              -999);
    this.d = deltas; // 保存卷积层的灵敏度

    for (int i = 0; i < inMapSize; i++) {
      Double[][] image = new Double[inputSize.GetLeftElement()][inputSize.GetRightElement()];
      for (int j = 0; j < inputSize.GetLeftElement(); j++)
        for (int k = 0; k < inputSize.GetRightElement(); k++) image[j][k] = 0.0;

      for (int j = 0; j < imageSize; j++) {
        image =
            MathUtils.addArrays(
                image,
                MathUtils.conv(deltas[j].getImage(), kernels[i][j].getRotatedKernel(), "full"));
      }
      deltaResult[i] = new ImageRecord(image, -999);
    }
    calculateGradient();
    this.batchCount += 1;
    // 按batchsize更新权重
    if (this.batchCount == batchSize - 1) {
      updateWeight(learningRate);
      this.batchCount = 0;
    }
    return deltaResult;
  }
  public ConvLayer(
      Pair<Integer, Integer> inputSize,
      Integer inMapSize,
      Integer outMapSize,
      Integer kernelSize,
      String activationFunction) {
    super();
    type = "Convolutional Layer";
    this.activationFunction = activationFunction;
    this.inputSize = new Pair<Integer, Integer>(inputSize);
    this.outputSize =
        new Pair<Integer, Integer>(
            inputSize.GetLeftElement() - kernelSize + 1,
            inputSize.GetRightElement() - kernelSize + 1);
    this.inMapSize = inMapSize;
    this.kernelSize = kernelSize;
    this.outMapSize = outMapSize;
    this.fan_in = inMapSize * (kernelSize * kernelSize); // 该卷积层的一个map对应的卷积核权重数
    this.fan_out = outMapSize * (kernelSize * kernelSize); // 该卷积层的卷积核权重数
    this.outputs = new ImageRecord[outMapSize];

    init_Kernels();
    init_b();
  }
  private static void startSession() {
    Session session = Session.getInstance(true);

    Pair<BigInteger, BigInteger> privateKeys = session.getPrivateKey();

    System.out.println("");
    System.out.println("Private key x: " + privateKeys.getFirst());
    System.out.println("Private key y: " + privateKeys.getSecond());
    System.out.println("");

    System.out.println("Please introduce message to sign:");
    String text = null;
    while (text == null) {
      try {
        text = (new BufferedReader(new InputStreamReader(System.in))).readLine();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    Pair<BigInteger, BigInteger> signature =
        DSA.sign(
            true,
            text,
            session.getGlobalKeyG(),
            session.getGlobalKeyP(),
            session.getGlobalKeyQ(),
            privateKeys.getFirst());
    System.out.println(
        "Signature (r,s): (" + signature.getFirst() + ", " + signature.getSecond() + ")");
    System.out.println("");
    System.out.println("Do you want to verify a message?");
    System.out.println("  1.Yes (y)");
    System.out.println("  2.No (press enter)");
    String alg = null;
    try {
      alg = (new BufferedReader(new InputStreamReader(System.in))).readLine();
    } catch (IOException e) {
      e.printStackTrace();
    }

    switch (alg) {
      case "y":
        verifyMessage();
        break;
      default:
        System.out.println("Bye!");
        System.exit(1);
        break;
    }
  }