问:
Planck's function in Fortran 90
I have the following formula for a function in Fortran 90 used to find the spectral radiance at a given wavelength and temperature. I've expressed it as:

```<code>intensity = (2.0d0*h*nu**(3.0d0))/c**(2.0d0) * 1d0 / (EXP((h*nu)/(k*T))-1d0)
</code>```

Where I take wavelength as an argument, which is then converted to nu. As my wavelengths tend to infinity, Fortran begins to say that the intensity is infinite, returning Inf. However, the Planck function converges to 0 as the wavelength tends to infinity. Why is this?

My theory is that perhaps, since nu = c/lambda, as lambda tends to infinity, a part of the function is divided by 0, so this tends it to infinity. However, there is also a -5 power law on wavelength as well, which is meant to overall keep the function converging at 0, but this doesn't seem to be the case by Fortran's computation. Why is this? What's going wrong? It's essentially saying zero times Inf is Inf.

For the record, I didn't think submitting blocks of my code was important here -- this is part of an exercise where this problem is meant to arise, so I know my code isn't malfunctioning.

Title: Planck's function in Fortran 90

Body:
I have the following formula for a function in Fortran 90 used to find the spectral radiance at a given wavelength and temperature. I've expressed it as:

intensity = (2.0d0*h*nu**(3.0d0))/c**(2.0d0) * 1d0 / (EXP((h*nu)/(k*T))-1d0)

Where I take wavelength as an argument, which is then converted to nu. As my wavelengths tend to infinity, Fortran begins to say that the intensity is infinite, returning Inf. However, the Planck function converges to 0 as the wavelength tends to infinity. Why is this?

My theory is that perhaps, since nu = c/lambda, as lambda tends to infinity, a part of the function is divided by 0, so this tends it to infinity. However, there is also a -5 power law on wavelength as well, which is meant to overall keep the function converging at 0, but this doesn't seem to be the case by Fortran's computation. Why is this? What's going wrong? It's essentially saying zero times Inf is Inf.

For the record, I didn't think submitting blocks of my code was important here -- this is part of an exercise where this problem is meant to arise, so I know my code isn't malfunctioning.

Body:
I think it is because exp(x) - 1 in the denominator becomes exactly 0 (in double precision) for very small x (cf. Loss of significance), while the numerator remains nonzero for the same x.

program main
    implicit none
    integer, parameter :: dp = kind(0.0d0)
    real(dp) :: nu, h, kT, ana, lim, numer, denom, expfac

    h = 0.8d0; kT = 1.2d0

    nu = 1.0d0
    do while ( nu > 1.0d-20 )

        expfac = exp((h * nu) / kT)
        numer = 2.0d0 * h * nu**3   ! (nu**3.0d0 also works but nu**3 is recommended)
        denom = expfac - 1.0d0

        !! Intensity (analytical & limiting expressions).
        ana = numer / denom
        lim = 2.0d0 * nu**2 * kT   !! use exp(x) ~ 1 + x

        print "(5(2x,a,es9.2),2x,a,es24.17)", &
                "nu=", nu, "ana=", ana, "lim=", lim, &
                "numer=", numer, "denom=", denom, "exp=", expfac

        nu = nu / 2.0d0
    enddo
end

Result (gfortran-9)

  nu= 1.00E+00  ana= 1.69E+00  lim= 2.40E+00  numer= 1.60E+00  denom= 9.48E-01  exp= 1.94773404105467596E+00
  nu= 5.00E-01  ana= 5.06E-01  lim= 6.00E-01  numer= 2.00E-01  denom= 3.96E-01  exp= 1.39561242508608951E+00
  nu= 2.50E-01  ana= 1.38E-01  lim= 1.50E-01  numer= 2.50E-02  denom= 1.81E-01  exp= 1.18136041286564608E+00
  nu= 1.25E-01  ana= 3.60E-02  lim= 3.75E-02  numer= 3.13E-03  denom= 8.69E-02  exp= 1.08690404952122899E+00
  nu= 6.25E-02  ana= 9.18E-03  lim= 9.37E-03  numer= 3.91E-04  denom= 4.25E-02  exp= 1.04254690518999138E+00
  nu= 3.12E-02  ana= 2.32E-03  lim= 2.34E-03  numer= 4.88E-05  denom= 2.11E-02  exp= 1.02105186214510746E+00
  nu= 1.56E-02  ana= 5.83E-04  lim= 5.86E-04  numer= 6.10E-06  denom= 1.05E-02  exp= 1.01047110901059778E+00
  nu= 7.81E-03  ana= 1.46E-04  lim= 1.46E-04  numer= 7.63E-07  denom= 5.22E-03  exp= 1.00522192027959556E+00
  nu= 3.91E-03  ana= 3.66E-05  lim= 3.66E-05  numer= 9.54E-08  denom= 2.61E-03  exp= 1.00260756045403721E+00
  nu= 1.95E-03  ana= 9.15E-06  lim= 9.16E-06  numer= 1.19E-08  denom= 1.30E-03  exp= 1.00130293141188642E+00
  nu= 9.77E-04  ana= 2.29E-06  lim= 2.29E-06  numer= 1.49E-09  denom= 6.51E-04  exp= 1.00065125364029117E+00
  nu= 4.88E-04  ana= 5.72E-07  lim= 5.72E-07  numer= 1.86E-10  denom= 3.26E-04  exp= 1.00032557382098908E+00
  nu= 2.44E-04  ana= 1.43E-07  lim= 1.43E-07  numer= 2.33E-11  denom= 1.63E-04  exp= 1.00016277366286199E+00
  nu= 1.22E-04  ana= 3.58E-08  lim= 3.58E-08  numer= 2.91E-12  denom= 8.14E-05  exp= 1.00008138351979237E+00
  nu= 6.10E-05  ana= 8.94E-09  lim= 8.94E-09  numer= 3.64E-13  denom= 4.07E-05  exp= 1.00004069093202008E+00
  nu= 3.05E-05  ana= 2.24E-09  lim= 2.24E-09  numer= 4.55E-14  denom= 2.03E-05  exp= 1.00002034525904526E+00
  nu= 1.53E-05  ana= 5.59E-10  lim= 5.59E-10  numer= 5.68E-15  denom= 1.02E-05  exp= 1.00001017257778191E+00
  nu= 7.63E-06  ana= 1.40E-10  lim= 1.40E-10  numer= 7.11E-16  denom= 5.09E-06  exp= 1.00000508627595597E+00
  nu= 3.81E-06  ana= 3.49E-11  lim= 3.49E-11  numer= 8.88E-17  denom= 2.54E-06  exp= 1.00000254313474413E+00
  nu= 1.91E-06  ana= 8.73E-12  lim= 8.73E-12  numer= 1.11E-17  denom= 1.27E-06  exp= 1.00000127156656360E+00
  nu= 9.54E-07  ana= 2.18E-12  lim= 2.18E-12  numer= 1.39E-18  denom= 6.36E-07  exp= 1.00000063578307974E+00
  nu= 4.77E-07  ana= 5.46E-13  lim= 5.46E-13  numer= 1.73E-19  denom= 3.18E-07  exp= 1.00000031789148935E+00
  nu= 2.38E-07  ana= 1.36E-13  lim= 1.36E-13  numer= 2.17E-20  denom= 1.59E-07  exp= 1.00000015894573213E+00
  nu= 1.19E-07  ana= 3.41E-14  lim= 3.41E-14  numer= 2.71E-21  denom= 7.95E-08  exp= 1.00000007947286296E+00
  nu= 5.96E-08  ana= 8.53E-15  lim= 8.53E-15  numer= 3.39E-22  denom= 3.97E-08  exp= 1.00000003973643059E+00
  nu= 2.98E-08  ana= 2.13E-15  lim= 2.13E-15  numer= 4.24E-23  denom= 1.99E-08  exp= 1.00000001986821507E+00
  nu= 1.49E-08  ana= 5.33E-16  lim= 5.33E-16  numer= 5.29E-24  denom= 9.93E-09  exp= 1.00000000993410754E+00
  nu= 7.45E-09  ana= 1.33E-16  lim= 1.33E-16  numer= 6.62E-25  denom= 4.97E-09  exp= 1.00000000496705366E+00
  nu= 3.73E-09  ana= 3.33E-17  lim= 3.33E-17  numer= 8.27E-26  denom= 2.48E-09  exp= 1.00000000248352694E+00
  nu= 1.86E-09  ana= 8.33E-18  lim= 8.33E-18  numer= 1.03E-26  denom= 1.24E-09  exp= 1.00000000124176336E+00
  nu= 9.31E-10  ana= 2.08E-18  lim= 2.08E-18  numer= 1.29E-27  denom= 6.21E-10  exp= 1.00000000062088179E+00
  nu= 4.66E-10  ana= 5.20E-19  lim= 5.20E-19  numer= 1.62E-28  denom= 3.10E-10  exp= 1.00000000031044078E+00
  nu= 2.33E-10  ana= 1.30E-19  lim= 1.30E-19  numer= 2.02E-29  denom= 1.55E-10  exp= 1.00000000015522050E+00
  nu= 1.16E-10  ana= 3.25E-20  lim= 3.25E-20  numer= 2.52E-30  denom= 7.76E-11  exp= 1.00000000007761014E+00
  nu= 5.82E-11  ana= 8.13E-21  lim= 8.13E-21  numer= 3.16E-31  denom= 3.88E-11  exp= 1.00000000003880518E+00
  nu= 2.91E-11  ana= 2.03E-21  lim= 2.03E-21  numer= 3.94E-32  denom= 1.94E-11  exp= 1.00000000001940248E+00
  nu= 1.46E-11  ana= 5.08E-22  lim= 5.08E-22  numer= 4.93E-33  denom= 9.70E-12  exp= 1.00000000000970135E+00
  nu= 7.28E-12  ana= 1.27E-22  lim= 1.27E-22  numer= 6.16E-34  denom= 4.85E-12  exp= 1.00000000000485056E+00
  nu= 3.64E-12  ana= 3.18E-23  lim= 3.18E-23  numer= 7.70E-35  denom= 2.43E-12  exp= 1.00000000000242539E+00
  nu= 1.82E-12  ana= 7.94E-24  lim= 7.94E-24  numer= 9.63E-36  denom= 1.21E-12  exp= 1.00000000000121259E+00
  nu= 9.09E-13  ana= 1.98E-24  lim= 1.99E-24  numer= 1.20E-36  denom= 6.06E-13  exp= 1.00000000000060640E+00
  nu= 4.55E-13  ana= 4.96E-25  lim= 4.96E-25  numer= 1.50E-37  denom= 3.03E-13  exp= 1.00000000000030309E+00
  nu= 2.27E-13  ana= 1.24E-25  lim= 1.24E-25  numer= 1.88E-38  denom= 1.52E-13  exp= 1.00000000000015166E+00
  nu= 1.14E-13  ana= 3.10E-26  lim= 3.10E-26  numer= 2.35E-39  denom= 7.57E-14  exp= 1.00000000000007572E+00
  nu= 5.68E-14  ana= 7.74E-27  lim= 7.75E-27  numer= 2.94E-40  denom= 3.80E-14  exp= 1.00000000000003797E+00
  nu= 2.84E-14  ana= 1.95E-27  lim= 1.94E-27  numer= 3.67E-41  denom= 1.89E-14  exp= 1.00000000000001887E+00
  nu= 1.42E-14  ana= 4.81E-28  lim= 4.85E-28  numer= 4.59E-42  denom= 9.55E-15  exp= 1.00000000000000955E+00
  nu= 7.11E-15  ana= 1.23E-28  lim= 1.21E-28  numer= 5.74E-43  denom= 4.66E-15  exp= 1.00000000000000466E+00
  nu= 3.55E-15  ana= 2.94E-29  lim= 3.03E-29  numer= 7.17E-44  denom= 2.44E-15  exp= 1.00000000000000244E+00
  nu= 1.78E-15  ana= 8.08E-30  lim= 7.57E-30  numer= 8.97E-45  denom= 1.11E-15  exp= 1.00000000000000111E+00
  nu= 8.88E-16  ana= 1.68E-30  lim= 1.89E-30  numer= 1.12E-45  denom= 6.66E-16  exp= 1.00000000000000067E+00
  nu= 4.44E-16  ana= 6.31E-31  lim= 4.73E-31  numer= 1.40E-46  denom= 2.22E-16  exp= 1.00000000000000022E+00
  nu= 2.22E-16  ana= 7.89E-32  lim= 1.18E-31  numer= 1.75E-47  denom= 2.22E-16  exp= 1.00000000000000022E+00
  nu= 1.11E-16  ana= Infinity  lim= 2.96E-32  numer= 2.19E-48  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 5.55E-17  ana= Infinity  lim= 7.40E-33  numer= 2.74E-49  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 2.78E-17  ana= Infinity  lim= 1.85E-33  numer= 3.42E-50  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 1.39E-17  ana= Infinity  lim= 4.62E-34  numer= 4.28E-51  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 6.94E-18  ana= Infinity  lim= 1.16E-34  numer= 5.35E-52  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 3.47E-18  ana= Infinity  lim= 2.89E-35  numer= 6.68E-53  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 1.73E-18  ana= Infinity  lim= 7.22E-36  numer= 8.35E-54  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 8.67E-19  ana= Infinity  lim= 1.81E-36  numer= 1.04E-54  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 4.34E-19  ana= Infinity  lim= 4.51E-37  numer= 1.31E-55  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 2.17E-19  ana= Infinity  lim= 1.13E-37  numer= 1.63E-56  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 1.08E-19  ana= Infinity  lim= 2.82E-38  numer= 2.04E-57  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 5.42E-20  ana= Infinity  lim= 7.05E-39  numer= 2.55E-58  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 2.71E-20  ana= Infinity  lim= 1.76E-39  numer= 3.19E-59  denom= 0.00E+00  exp= 1.00000000000000000E+00
  nu= 1.36E-20  ana= Infinity  lim= 4.41E-40  numer= 3.98E-60  denom= 0.00E+00  exp= 1.00000000000000000E+00

According to this page, exp(x) - 1 (for small x) can be evaluated in a more stable manner as 2 * tanh(x/2) / (1 - tanh(x/2)). The latter expression indeed seems to improve the result.

program main
    implicit none
    integer, parameter :: dp = kind(0.0d0)
    real(dp) :: nu, h, kT, ana, lim, numer, denom, expfac, x

    h = 0.8d0; kT = 1.2d0

    nu = 1.0d0
    do while ( nu > 1.0d-20 )

        x = h * nu / kT
        numer = 2.0d0 * h * nu**3
        denom = (2 * tanh(x / 2)) / (1 - tanh(x / 2))

        ana = numer / denom
        lim = 2.0d0 * nu**2 * kT

        print "(5(2x,a,es9.2))", &
                "nu=", nu, "ana=", ana, "lim=", lim, &
                "numer=", numer, "denom=", denom

        nu = nu / 2.0d0
    enddo
end

Result:

  nu= 1.00E+00  ana= 1.69E+00  lim= 2.40E+00  numer= 1.60E+00  denom= 9.48E-01
  nu= 5.00E-01  ana= 5.06E-01  lim= 6.00E-01  numer= 2.00E-01  denom= 3.96E-01
  nu= 2.50E-01  ana= 1.38E-01  lim= 1.50E-01  numer= 2.50E-02  denom= 1.81E-01
  nu= 1.25E-01  ana= 3.60E-02  lim= 3.75E-02  numer= 3.13E-03  denom= 8.69E-02
  nu= 6.25E-02  ana= 9.18E-03  lim= 9.37E-03  numer= 3.91E-04  denom= 4.25E-02
  nu= 3.12E-02  ana= 2.32E-03  lim= 2.34E-03  numer= 4.88E-05  denom= 2.11E-02
  nu= 1.56E-02  ana= 5.83E-04  lim= 5.86E-04  numer= 6.10E-06  denom= 1.05E-02
  nu= 7.81E-03  ana= 1.46E-04  lim= 1.46E-04  numer= 7.63E-07  denom= 5.22E-03
  nu= 3.91E-03  ana= 3.66E-05  lim= 3.66E-05  numer= 9.54E-08  denom= 2.61E-03
  nu= 1.95E-03  ana= 9.15E-06  lim= 9.16E-06  numer= 1.19E-08  denom= 1.30E-03
  nu= 9.77E-04  ana= 2.29E-06  lim= 2.29E-06  numer= 1.49E-09  denom= 6.51E-04
  nu= 4.88E-04  ana= 5.72E-07  lim= 5.72E-07  numer= 1.86E-10  denom= 3.26E-04
  nu= 2.44E-04  ana= 1.43E-07  lim= 1.43E-07  numer= 2.33E-11  denom= 1.63E-04
  nu= 1.22E-04  ana= 3.58E-08  lim= 3.58E-08  numer= 2.91E-12  denom= 8.14E-05
  nu= 6.10E-05  ana= 8.94E-09  lim= 8.94E-09  numer= 3.64E-13  denom= 4.07E-05
  nu= 3.05E-05  ana= 2.24E-09  lim= 2.24E-09  numer= 4.55E-14  denom= 2.03E-05
  nu= 1.53E-05  ana= 5.59E-10  lim= 5.59E-10  numer= 5.68E-15  denom= 1.02E-05
  nu= 7.63E-06  ana= 1.40E-10  lim= 1.40E-10  numer= 7.11E-16  denom= 5.09E-06
  nu= 3.81E-06  ana= 3.49E-11  lim= 3.49E-11  numer= 8.88E-17  denom= 2.54E-06
  nu= 1.91E-06  ana= 8.73E-12  lim= 8.73E-12  numer= 1.11E-17  denom= 1.27E-06
  nu= 9.54E-07  ana= 2.18E-12  lim= 2.18E-12  numer= 1.39E-18  denom= 6.36E-07
  nu= 4.77E-07  ana= 5.46E-13  lim= 5.46E-13  numer= 1.73E-19  denom= 3.18E-07
  nu= 2.38E-07  ana= 1.36E-13  lim= 1.36E-13  numer= 2.17E-20  denom= 1.59E-07
  nu= 1.19E-07  ana= 3.41E-14  lim= 3.41E-14  numer= 2.71E-21  denom= 7.95E-08
  nu= 5.96E-08  ana= 8.53E-15  lim= 8.53E-15  numer= 3.39E-22  denom= 3.97E-08
  nu= 2.98E-08  ana= 2.13E-15  lim= 2.13E-15  numer= 4.24E-23  denom= 1.99E-08
  nu= 1.49E-08  ana= 5.33E-16  lim= 5.33E-16  numer= 5.29E-24  denom= 9.93E-09
  nu= 7.45E-09  ana= 1.33E-16  lim= 1.33E-16  numer= 6.62E-25  denom= 4.97E-09
  nu= 3.73E-09  ana= 3.33E-17  lim= 3.33E-17  numer= 8.27E-26  denom= 2.48E-09
  nu= 1.86E-09  ana= 8.33E-18  lim= 8.33E-18  numer= 1.03E-26  denom= 1.24E-09
  nu= 9.31E-10  ana= 2.08E-18  lim= 2.08E-18  numer= 1.29E-27  denom= 6.21E-10
  nu= 4.66E-10  ana= 5.20E-19  lim= 5.20E-19  numer= 1.62E-28  denom= 3.10E-10
  nu= 2.33E-10  ana= 1.30E-19  lim= 1.30E-19  numer= 2.02E-29  denom= 1.55E-10
  nu= 1.16E-10  ana= 3.25E-20  lim= 3.25E-20  numer= 2.52E-30  denom= 7.76E-11
  nu= 5.82E-11  ana= 8.13E-21  lim= 8.13E-21  numer= 3.16E-31  denom= 3.88E-11
  nu= 2.91E-11  ana= 2.03E-21  lim= 2.03E-21  numer= 3.94E-32  denom= 1.94E-11
  nu= 1.46E-11  ana= 5.08E-22  lim= 5.08E-22  numer= 4.93E-33  denom= 9.70E-12
  nu= 7.28E-12  ana= 1.27E-22  lim= 1.27E-22  numer= 6.16E-34  denom= 4.85E-12
  nu= 3.64E-12  ana= 3.18E-23  lim= 3.18E-23  numer= 7.70E-35  denom= 2.43E-12
  nu= 1.82E-12  ana= 7.94E-24  lim= 7.94E-24  numer= 9.63E-36  denom= 1.21E-12
  nu= 9.09E-13  ana= 1.99E-24  lim= 1.99E-24  numer= 1.20E-36  denom= 6.06E-13
  nu= 4.55E-13  ana= 4.96E-25  lim= 4.96E-25  numer= 1.50E-37  denom= 3.03E-13
  nu= 2.27E-13  ana= 1.24E-25  lim= 1.24E-25  numer= 1.88E-38  denom= 1.52E-13
  nu= 1.14E-13  ana= 3.10E-26  lim= 3.10E-26  numer= 2.35E-39  denom= 7.58E-14
  nu= 5.68E-14  ana= 7.75E-27  lim= 7.75E-27  numer= 2.94E-40  denom= 3.79E-14
  nu= 2.84E-14  ana= 1.94E-27  lim= 1.94E-27  numer= 3.67E-41  denom= 1.89E-14
  nu= 1.42E-14  ana= 4.85E-28  lim= 4.85E-28  numer= 4.59E-42  denom= 9.47E-15
  nu= 7.11E-15  ana= 1.21E-28  lim= 1.21E-28  numer= 5.74E-43  denom= 4.74E-15
  nu= 3.55E-15  ana= 3.03E-29  lim= 3.03E-29  numer= 7.17E-44  denom= 2.37E-15
  nu= 1.78E-15  ana= 7.57E-30  lim= 7.57E-30  numer= 8.97E-45  denom= 1.18E-15
  nu= 8.88E-16  ana= 1.89E-30  lim= 1.89E-30  numer= 1.12E-45  denom= 5.92E-16
  nu= 4.44E-16  ana= 4.73E-31  lim= 4.73E-31  numer= 1.40E-46  denom= 2.96E-16
  nu= 2.22E-16  ana= 1.18E-31  lim= 1.18E-31  numer= 1.75E-47  denom= 1.48E-16
  nu= 1.11E-16  ana= 2.96E-32  lim= 2.96E-32  numer= 2.19E-48  denom= 7.40E-17
  nu= 5.55E-17  ana= 7.40E-33  lim= 7.40E-33  numer= 2.74E-49  denom= 3.70E-17
  nu= 2.78E-17  ana= 1.85E-33  lim= 1.85E-33  numer= 3.42E-50  denom= 1.85E-17
  nu= 1.39E-17  ana= 4.62E-34  lim= 4.62E-34  numer= 4.28E-51  denom= 9.25E-18
  nu= 6.94E-18  ana= 1.16E-34  lim= 1.16E-34  numer= 5.35E-52  denom= 4.63E-18
  nu= 3.47E-18  ana= 2.89E-35  lim= 2.89E-35  numer= 6.68E-53  denom= 2.31E-18
  nu= 1.73E-18  ana= 7.22E-36  lim= 7.22E-36  numer= 8.35E-54  denom= 1.16E-18
  nu= 8.67E-19  ana= 1.81E-36  lim= 1.81E-36  numer= 1.04E-54  denom= 5.78E-19
  nu= 4.34E-19  ana= 4.51E-37  lim= 4.51E-37  numer= 1.31E-55  denom= 2.89E-19
  nu= 2.17E-19  ana= 1.13E-37  lim= 1.13E-37  numer= 1.63E-56  denom= 1.45E-19
  nu= 1.08E-19  ana= 2.82E-38  lim= 2.82E-38  numer= 2.04E-57  denom= 7.23E-20
  nu= 5.42E-20  ana= 7.05E-39  lim= 7.05E-39  numer= 2.55E-58  denom= 3.61E-20
  nu= 2.71E-20  ana= 1.76E-39  lim= 1.76E-39  numer= 3.19E-59  denom= 1.81E-20
  nu= 1.36E-20  ana= 4.41E-40  lim= 4.41E-40  numer= 3.98E-60  denom= 9.04E-21


来源: stackexchange

问:
Running text2column for column A:A
I am quite new to VBA scripting, but I have to perform the following actions:

convert a csv file to xls one

in the saved xls file to perform the following actions:
         1. To run Text To Columns  for the data
         2. To define the type of each column ( amount , date, text).
         3. To make the first 0 in Amount&Date columns be visible ( e.g. "04521.6823" & for date "05/02/2020"). Here  I plan to use .NumberFormat option.

I succesfully converted the file, but cannot perform Text2Column part.
My data is only in column A, separator ";", only on sheet1.
Here is the latest code I ran:

```<code> Sub text2columns()
    Dim rg As Range

    Set rg = Range("A:A").CurrentRegion

    rg.TextToColumns Destination:=Range("A:A"), ConsecutiveDelimiter:=True, DataType:=xlDelimited, Space:=True

    End Sub
</code>```

Can anyone help me? I know questions are basic, but need some help to continue.
Thank you!

答:
Try this code, please:

```<code>Sub text2columns()
    Dim rg As Range, arrFlInf(19) As Variant, i As Long
    For i = 0 To UBound(arrFlInf)
        Select Case i
            Case 1 - 8, 10   'Text
                arrFlInf(i) = Array(i + 1, 2)
            Case 12 - 15, 18 'date (MDY)
                arrFlInf(i) = Array(i + 1, 3)
            Case Else        'General
                arrFlInf(i) = Array(i + 1, 1)
        End Select
    Next i
    Set rg = Range("A:A")

    rg.TextToColumns Destination:=Range("A1"), _
        ConsecutiveDelimiter:=False, _
        DataType:=xlDelimited, _
        Semicolon:=True, _
        fieldInfo:=arrFlInf
End Sub
</code>```

If you do not need the date format to be of type "MDY", you must change it in one of the next categories: 4 = DMY, 5 = YMD, 6 = MYD, 7 = DYM and 8 = YDM.

ContentLicense: CC BY-SA 4.0

Title: Running text2column for column A:A

Body:
I am quite new to VBA scripting, but I have to perform the following actions:

convert a csv file to xls one

in the saved xls file to perform the following actions:
         1. To run Text To Columns  for the data
         2. To define the type of each column ( amount , date, text).
         3. To make the first 0 in Amount&Date columns be visible ( e.g. "04521.6823" & for date "05/02/2020"). Here  I plan to use .NumberFormat option.

I succesfully converted the file, but cannot perform Text2Column part.
My data is only in column A, separator ";", only on sheet1.
Here is the latest code I ran:

 Sub text2columns()
    Dim rg As Range

    Set rg = Range("A:A").CurrentRegion

    rg.TextToColumns Destination:=Range("A:A"), ConsecutiveDelimiter:=True, DataType:=xlDelimited, Space:=True

    End Sub

Can anyone help me? I know questions are basic, but need some help to continue.
Thank you!

Body:
Try this code, please:

Sub text2columns()
    Dim rg As Range, arrFlInf(19) As Variant, i As Long
    For i = 0 To UBound(arrFlInf)
        Select Case i
            Case 1 - 8, 10   'Text
                arrFlInf(i) = Array(i + 1, 2)
            Case 12 - 15, 18 'date (MDY)
                arrFlInf(i) = Array(i + 1, 3)
            Case Else        'General
                arrFlInf(i) = Array(i + 1, 1)
        End Select
    Next i
    Set rg = Range("A:A")

    rg.TextToColumns Destination:=Range("A1"), _
        ConsecutiveDelimiter:=False, _
        DataType:=xlDelimited, _
        Semicolon:=True, _
        fieldInfo:=arrFlInf
End Sub

If you do not need the date format to be of type "MDY", you must change it in one of the next categories: 4 = DMY, 5 = YMD, 6 = MYD, 7 = DYM and 8 = YDM.


答:
Does the following code fulfill your requirement?

```<code>SELECT
    *, SUM(Credit - Debit) OVER (PARTITION BY ClientCode ORDER BY RunDater) AS Amount
INTO #temp
FROM DPI AS Amount

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((select distinct ',
            SUM(CASE WHEN [RunDater]=''' + CAST([RunDater] as varchar(10)) + ''' THEN [Interest] ELSE 0 END) AS [' + CAST([RunDater] as varchar(10)) + ' Interest],
            SUM(CASE WHEN [RunDater]=''' + CAST([RunDater] as varchar(10)) + ''' THEN [Amount] ELSE 0 END) AS [' + CAST([RunDater] as varchar(10)) + ' Amount]'
            /*---------------You can add other columns here similar to above--------------*/
            FROM #temp
            FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')
SET @query = 'SELECT ClientCode, ' + @Cols + '  FROM #temp group by ClientCode'

--print (@query)
exec(@query)
</code>```

dbfiddle demo

Title: Form pivot table for more than two dynamic column

Body:
I have created this table

CREATE TABLE [DPI]
(
    [ClientCode] [varchar](20) NULL,
    [RunDater] [date] NULL,
    [Debit] [numeric](18, 2) NULL,
    [Credit] [numeric](18, 2) NULL,
    [DayOfDifference] [numeric](18, 0) NULL,
    [Interest] [numeric](18, 2) NULL
 )

Inserted values:

 INSERT INTO DPI (ClientCode, RunDater, Debit, Credit, DayOfDifference, Interest)
 VALUES
 ('Z001','20/01/2001',20,0,0,18)
 ,('Z001','21/01/2001',0,0,0 ,0)
 ,('Z001','22/01/2001',40,20,0 ,0)
 ,('Z001','23/01/2001',0,0,0,0)
 ,('Z001','24/01/2001',0,20,0 ,0)
 ,('Z001','25/01/2001',100,0,0,0)
 ,('Z001','26/01/2001',0,0,0,0)
 ,('Z002','20/01/2001',0,0 ,0,0)
 ,('Z002','21/01/2001',0,0,0,0)
 ,('Z002','22/01/2001',30,20,0,0)
 ,('Z002','23/01/2001',0,0,0 ,0)
 ,('Z002','24/01/2001',0,20,0,0)
  ,('Z002','25/01/2001',100,0,0,0)
 ,('Z002','26/01/2001',0,0,0,0)

I wrote this query for getting the running balance and store in temporary table:

SELECT
    *, SUM(Credit - Debit) OVER (PARTITION BY ClientCode ORDER BY RunDater) AS Amount
INTO #temp
FROM DPI AS Amount

Now my table looks like this:

and want output in this format:

Body:
Does the following code fulfill your requirement?

SELECT
    *, SUM(Credit - Debit) OVER (PARTITION BY ClientCode ORDER BY RunDater) AS Amount
INTO #temp
FROM DPI AS Amount

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((select distinct ',
            SUM(CASE WHEN [RunDater]=''' + CAST([RunDater] as varchar(10)) + ''' THEN [Interest] ELSE 0 END) AS [' + CAST([RunDater] as varchar(10)) + ' Interest],
            SUM(CASE WHEN [RunDater]=''' + CAST([RunDater] as varchar(10)) + ''' THEN [Amount] ELSE 0 END) AS [' + CAST([RunDater] as varchar(10)) + ' Amount]'
            /*---------------You can add other columns here similar to above--------------*/
            FROM #temp
            FOR XML PATH(''),type).value('.','varchar(max)'),1,2,'')
SET @query = 'SELECT ClientCode, ' + @Cols + '  FROM #temp group by ClientCode'

--print (@query)
exec(@query)

dbfiddle demo


问:
What is the best way to learn backbone.js? Any other alternatives?
I'm just starting to get into backbone.js. It looks like it's pretty involved and won't be something you can just look at one example and say, "Well, that's easy!" and start being productive with it. It does look good though.

The documentation is okay, but I find myself not understanding the 'big picture' very well, and how all of these components work together. The way events are bound and rendered in the various views actually seems like a lot of entanglements. I understand the need for separation of concerns, but I am actually wondering if it's just a tad over-engineered.

Essentially... I won't be able to be immediately productive with backbone.js. There is going to be a a day or two learning curve I think.

What is the best way to get into backbone.js? Just keep chugging along, or are there some larger sample applications to download somewhere to look at?

Are there better alternatives that might be easier to learn and offer the same sort of benefits? For me, productivity and intuitiveness are pretty important. I sort of feel like the way backbone.js works is a little foreign. That could just be me.

Put another way, would it maybe be better to develop my application without a library like backbone and sort of organically create a framework like backbone.js but more like something that is intuitive to me and something more inline with the resultant code base?

I've been trying to get simple examples to work with my own code, and I get no Javascript errors... but it doesn't work. There's a good chance that "one minor thing" is wrong... but I'm beginning to feel that debugging my backbone applications might be a problem... so perhaps organically growing my own might actually be a better option for my own sanity. Debugging in the dark is a real productivity killer... and honestly, I'd rather do my own framework and write my own code if it spares me hours of endless debugging.

I don't know what to do - hence why I am asking.

答:
As with learning a lot of programming related things, my advice would be:

Pick a task you think is suitable for what you're working with

Attempt to execute that task

If you find you're stuck, show the code you have and explain what you think should be happening. Make sure you check documentation to verify your functions work as you expect them to.

As you progress, people will also show you more standard and efficient ways to do things

Keep doing this until you become more familiar with how things work

Now, look over documentation in depth to help fully master how it works as a whole, continuing to ask questions

Pretty soon you'll be answering questions more than asking them

ContentLicense: CC BY-SA 3.0


问:
do NestJs or TypeScript provide premade exceptions like 'KeyNotFoundException'
I would like to create a NestJs backend and started with some REST endpoints but would like to support GraphQL later on too.

Let's assume I want to delete a user by id. The service layer knows if that user was deleted by checking the amount of deleted rows. If it's not zero, the user was deleted. If it's zero I want to throw a "Not found exception".

I know that Nest ships with some premade http exceptions https://docs.nestjs.com/exception-filters#built-in-http-exceptions. But I don't want to use those exceptions in my service layer because I think they should only be used in the HTTP layer (REST controllers).

So I created my own exceptions

```<code>export class KeyNotFoundException extends Error {
  constructor(message: string) {
    super(message);
  }
}
</code>```

and use them in my service layer and maybe repository layer too.

```<code>public async deleteUserById(id: number): Promise<void> {
  const deletedRows: number = await this.usersRepository.deleteUserById(id);

  if (deletedRows === 0) {
    // my custom exception
    throw new KeyNotFoundException(`User with Id ${id} not found`);
  }
}
</code>```

The controller could deal with this exception and throw a 404 or 500 if the error is not a KeyNotFoundException

```<code>@Delete(':id')
public async deleteUserById(@Param('id', ParseIntPipe) id: number): Promise<void> {
  try {
    await this.usersService.deleteUserById(id);
  } catch (error) {
    // my custom Exception
    if (error instanceof KeyNotFoundException) {
      // premade NestJs exception will throw 404
      throw new NotFoundException(error.message);
    }

    // premade NestJs exception will throw 500
    throw new InternalServerErrorException();
  }
}
</code>```

I am not satisfied with the solution because I have translate my custom exceptions to NestJs HTTP exceptions all the time. And maybe the service could come up with multiple exceptions, I would have to use a switch to check for the correct exception type.

Are there any better ideas on how to solve this?

C# for example comes with a KeyNotFoundException but I think for TypeScript I have to create my own exception system.

答: First of, I think your current solution is completely valid. If you don't want to throw http exception from the service and throw a NotFound in the controller, there is no way around converting the two. To make it easy, you can create a generic exception factory which knows how to translate your service exceptions to an http exception. You can also take care of it as part of the middleware and not worry about it on the controller side</p>

Body:
I would like to create a NestJs backend and started with some REST endpoints but would like to support GraphQL later on too.

Let's assume I want to delete a user by id. The service layer knows if that user was deleted by checking the amount of deleted rows. If it's not zero, the user was deleted. If it's zero I want to throw a "Not found exception".

I know that Nest ships with some premade http exceptions https://docs.nestjs.com/exception-filters#built-in-http-exceptions. But I don't want to use those exceptions in my service layer because I think they should only be used in the HTTP layer (REST controllers).

So I created my own exceptions

export class KeyNotFoundException extends Error {
  constructor(message: string) {
    super(message);
  }
}

and use them in my service layer and maybe repository layer too.

public async deleteUserById(id: number): Promise<void> {
  const deletedRows: number = await this.usersRepository.deleteUserById(id);

  if (deletedRows === 0) {
    // my custom exception
    throw new KeyNotFoundException(`User with Id ${id} not found`);
  }
}

The controller could deal with this exception and throw a 404 or 500 if the error is not a KeyNotFoundException

@Delete(':id')
public async deleteUserById(@Param('id', ParseIntPipe) id: number): Promise<void> {
  try {
    await this.usersService.deleteUserById(id);
  } catch (error) {
    // my custom Exception
    if (error instanceof KeyNotFoundException) {
      // premade NestJs exception will throw 404
      throw new NotFoundException(error.message);
    }

    // premade NestJs exception will throw 500
    throw new InternalServerErrorException();
  }
}

I am not satisfied with the solution because I have translate my custom exceptions to NestJs HTTP exceptions all the time. And maybe the service could come up with multiple exceptions, I would have to use a switch to check for the correct exception type.

Are there any better ideas on how to solve this?

C# for example comes with a KeyNotFoundException but I think for TypeScript I have to create my own exception system.


问:
Set a title programmatically
Here is my storyboard. My TabBarController references to the NavigationController (which has a own class) in the second picture.

I am not able to set a title via code. I tried every piece of code inside my MapsViewController & MapsNavigationViewController I found on Google & co.

viewController.title = "some title" <- not working

self.title = "some title" <- not working

navigationBar.topItem.title = "some title" <- not working

self.navigationItem.title = "Your Title" <- not working

self.parent?.title = "some title" <- not working

navigationItem.title = "What ever you want" <- not working

How can I set a title to my Navigation programmatically...?

1)

2)

3)

Edit: View Hierachy:

答: Solution: The title color should not be the same as the navigation bar color. Thanks to @kjoe.</p>

Title: Set a title programmatically


问:
A color object not working as a color unless recreated
I'm struggling with a descriptive title.

I'm trying to use the swing.plaf colors from NimbusLookAndFeel in a custom component of mine.
The colors i'm getting from UIManager looks good, but the setBackground and setForeground methods doesn't work with the colors im getting.

The following sample displays the very curious behaviour

```<code>package syscolorbug;

import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class SysColorBug {
    public static void main(String[] args) throws Exception {
        javax.swing.UIManager.
                setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

        Color background = javax.swing.UIManager.getDefaults().
                getColor("List[Selected].textBackground");
        JFrame jf = new JFrame();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLayout(new FlowLayout());
        jf.setSize(400,300);
        JLabel l = new JLabel("Text");
        l.setOpaque(true);
        jf.add(l);
        System.err.println(background);
        // This needs to happen for the color to be set.
        //24: background = new Color(background.getRGB());
        System.err.println(background);
        l.setBackground(background);
        jf.setVisible(true);
    }

}
</code>```

If i comment out 24: it works as intended.

The debug output on background shows

```<code>DerivedColor(color=57,105,138 parent=nimbusSelectionBackground offsets=0.0,0.0,0.0,0 pColor=57,105,138
</code>```

and

```<code>java.awt.Color[r=57,g=105,b=138]
</code>```

Further investigations shows that the problem doesn't seem to be affecting other LookAndFeels.

For instance on the Metal LAF produces

```<code>javax.swing.plaf.ColorUIResource[r=255,g=255,b=255]
</code>```

for the 'List.background' key.

Is this a bug in the Nimbus plaf?

I'd very much like to avoid the superflous background = new Color(background.getRGB());  is there an easy fix?

Java version is openjdk java 1.8.0.

答:
I don't do laf much when I do graphics so I don't understand why List[Selected].textBackground would be the background of the JLabel. The default appears to be color=214,217,223

This also seems to match what I saw and read at nimbus laf

Body:
I'm struggling with a descriptive title.

I'm trying to use the swing.plaf colors from NimbusLookAndFeel in a custom component of mine.
The colors i'm getting from UIManager looks good, but the setBackground and setForeground methods doesn't work with the colors im getting.

The following sample displays the very curious behaviour

package syscolorbug;

import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class SysColorBug {
    public static void main(String[] args) throws Exception {
        javax.swing.UIManager.
                setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

        Color background = javax.swing.UIManager.getDefaults().
                getColor("List[Selected].textBackground");
        JFrame jf = new JFrame();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLayout(new FlowLayout());
        jf.setSize(400,300);
        JLabel l = new JLabel("Text");
        l.setOpaque(true);
        jf.add(l);
        System.err.println(background);
        // This needs to happen for the color to be set.
        //24: background = new Color(background.getRGB());
        System.err.println(background);
        l.setBackground(background);
        jf.setVisible(true);
    }

}

If i comment out 24: it works as intended.

The debug output on background shows

DerivedColor(color=57,105,138 parent=nimbusSelectionBackground offsets=0.0,0.0,0.0,0 pColor=57,105,138

and

java.awt.Color[r=57,g=105,b=138]

Further investigations shows that the problem doesn't seem to be affecting other LookAndFeels.

For instance on the Metal LAF produces

javax.swing.plaf.ColorUIResource[r=255,g=255,b=255]

for the 'List.background' key.

Is this a bug in the Nimbus plaf?

I'd very much like to avoid the superflous background = new Color(background.getRGB());  is there an easy fix?

Java version is openjdk java 1.8.0.


问:
Getting IE to replace a regex with the literal string "$0"
I'm replacing a bunch of values in a regex with dollar amounts.  The problem is that in IE, if I attempt to replace with an amount of $0 (or, theoretically, $1--$9), the replace never occurs since the it's trying to replace a non-existant group:

```<code>'foo'.replace(/f/g, '$0');
</code>```

I want the result of that replacement to be "$0oo", which it is in Chrome & FF, but not IE9 (haven't tried other versions of IE).

Chrome & FF have an "issue" with the following, in that I can't figure out how to replace with a literal $1:

```<code>'foo'.replace(/(f)/g, '$1')
</code>```

答:
@SLaks that should be more like: write "$$" for literal "$".

@cwolves getting a literal instead of a 'special' character (like "$" here) usually involves either doubling it or prefixing it with "\".

Body:
I'm replacing a bunch of values in a regex with dollar amounts.  The problem is that in IE, if I attempt to replace with an amount of $0 (or, theoretically, $1--$9), the replace never occurs since the it's trying to replace a non-existant group:

'foo'.replace(/f/g, '$0');

I want the result of that replacement to be "$0oo", which it is in Chrome & FF, but not IE9 (haven't tried other versions of IE).

Chrome & FF have an "issue" with the following, in that I can't figure out how to replace with a literal $1:

'foo'.replace(/(f)/g, '$1')


问:
MySQL 5.7 : convert simple JSON_ARRAY to rows
I have a simple table with a JSON_ARRAY column like that:

```<code>+----+---------+
| id | content |
+----+---------+
|  1 | [3, 4]  |
|  2 | [5, 6]  |
+----+---------+
</code>```

I want to list all the content references for a specific id

SELECT JSON_EXTRACT(content, '$') as res FROM table WHERE id=1

But I'd like the result to be in rows:

```<code>+-----+
| res |
+-----+
|  3  |
|  4  |
+-----+
</code>```

答:
You can do this in MySQL 8.0 with JSON_TABLE():

```<code>select r.res from mytable,
 json_table(mytable.content, '$[*]' columns (res int path '$')) r
where mytable.id = 1
</code>```

I tested on MySQL 8.0.17, and this is the output:

```<code>+------+
| res  |
+------+
|    3 |
|    4 |
+------+
</code>```

If you use a version older than MySQL 8.0, you have these options:

Find some impossibly complex SQL solution. This is almost always the wrong way to solve the problem, because you end up with code that is too expensive to maintain.

Fetch the JSON array as-is, and explode it in application code.

Normalize your data so you have one value per row, instead of using JSON arrays.

I often find questions on Stack Overflow about using JSON in MySQL that convince me that this feature has ruined MySQL. Developers keep using it inappropriately. They like that it makes it easy to insert semi-structured data, but they find that it makes querying that data far too complex.

Re comment from @ChetanOswal:

There are solutions for MySQL 5.7, but they are unsatisfying and my advice is to avoid them.

Demo:

We can start with the data shown in the original question above.

```<code>mysql> create table mytable (id serial primary key, content json);

mysql> insert into mytable values
    -> (1, '[3,4]'),
    -> (2, '[5,6]');
</code>```

Next we need another table that simply has a series of integer values, at least as many as the longest JSON array.

```<code>mysql> create table numbers (number int primary key);

mysql> insert into numbers values (0), (1), (2);
</code>```

Joining these tables using an inequality we can create as many rows as the number of items in the JSON arrays.

```<code>mysql> select * from mytable
  join numbers on numbers.number < json_length(mytable.content);
+----+---------+--------+
| id | content | number |
+----+---------+--------+
|  1 | [3, 4]  |      0 |
|  1 | [3, 4]  |      1 |
|  2 | [5, 6]  |      0 |
|  2 | [5, 6]  |      1 |
+----+---------+--------+
</code>```

Now we can use those numbers as array indexes to extract the values from the JSON arrays.

```<code>mysql> select *,
  json_extract(mytable.content, concat('$[', numbers.number, ']')) as value
 from mytable
 join numbers on numbers.number < json_length(mytable.content);
+----+---------+--------+-------+
| id | content | number | value |
+----+---------+--------+-------+
|  1 | [3, 4]  |      0 | 3     |
|  1 | [3, 4]  |      1 | 4     |
|  2 | [5, 6]  |      0 | 5     |
|  2 | [5, 6]  |      1 | 6     |
+----+---------+--------+-------+
</code>```

That's as far as I will advise on solving this in MySQL 5.7.

If you need features that are in MySQL 8.0, then you should upgrade to MySQL 8.0.

MySQL 5.7 is nearing its end of life in October 2023. It's time to upgrade anyway.

If you can't upgrade, and you don't like workaround solutions like I showed, then you should stop using SQL to work with JSON.

Body:
I have a simple table with a JSON_ARRAY column like that:

+----+---------+
| id | content |
+----+---------+
|  1 | [3, 4]  |
|  2 | [5, 6]  |
+----+---------+

I want to list all the content references for a specific id

SELECT JSON_EXTRACT(content, '$') as res FROM table WHERE id=1

But I'd like the result to be in rows:

+-----+
| res |
+-----+
|  3  |
|  4  |
+-----+

Body:
You can do this in MySQL 8.0 with JSON_TABLE():

select r.res from mytable,
 json_table(mytable.content, '$[*]' columns (res int path '$')) r
where mytable.id = 1

I tested on MySQL 8.0.17, and this is the output:

+------+
| res  |
+------+
|    3 |
|    4 |
+------+

If you use a version older than MySQL 8.0, you have these options:

Find some impossibly complex SQL solution. This is almost always the wrong way to solve the problem, because you end up with code that is too expensive to maintain.

Fetch the JSON array as-is, and explode it in application code.

Normalize your data so you have one value per row, instead of using JSON arrays.

I often find questions on Stack Overflow about using JSON in MySQL that convince me that this feature has ruined MySQL. Developers keep using it inappropriately. They like that it makes it easy to insert semi-structured data, but they find that it makes querying that data far too complex.

Re comment from @ChetanOswal:

There are solutions for MySQL 5.7, but they are unsatisfying and my advice is to avoid them.

Demo:

We can start with the data shown in the original question above.

mysql> create table mytable (id serial primary key, content json);

mysql> insert into mytable values
    -> (1, '[3,4]'),
    -> (2, '[5,6]');

Next we need another table that simply has a series of integer values, at least as many as the longest JSON array.

mysql> create table numbers (number int primary key);

mysql> insert into numbers values (0), (1), (2);

Joining these tables using an inequality we can create as many rows as the number of items in the JSON arrays.

mysql> select * from mytable
  join numbers on numbers.number < json_length(mytable.content);
+----+---------+--------+
| id | content | number |
+----+---------+--------+
|  1 | [3, 4]  |      0 |
|  1 | [3, 4]  |      1 |
|  2 | [5, 6]  |      0 |
|  2 | [5, 6]  |      1 |
+----+---------+--------+

Now we can use those numbers as array indexes to extract the values from the JSON arrays.

mysql> select *,
  json_extract(mytable.content, concat('$[', numbers.number, ']')) as value
 from mytable
 join numbers on numbers.number < json_length(mytable.content);
+----+---------+--------+-------+
| id | content | number | value |
+----+---------+--------+-------+
|  1 | [3, 4]  |      0 | 3     |
|  1 | [3, 4]  |      1 | 4     |
|  2 | [5, 6]  |      0 | 5     |
|  2 | [5, 6]  |      1 | 6     |
+----+---------+--------+-------+

That's as far as I will advise on solving this in MySQL 5.7.

If you need features that are in MySQL 8.0, then you should upgrade to MySQL 8.0.

MySQL 5.7 is nearing its end of life in October 2023. It's time to upgrade anyway.

If you can't upgrade, and you don't like workaround solutions like I showed, then you should stop using SQL to work with JSON.


问:
Best Practices for storing a List of Values set using a NoSQL Database
I am working on a solution that uses a NoSQL backend.  My experience is traditionally with relational databases and would like to discuss the best way to store a list of values which may appear in a drop-down from the UI.  Traditonally, I would just create a table in my relational DB to store that small set of values and then my records would tie to a specific id representing that value.  A simple example of this is a Person table with all of my person records and a Hair color list of values with all the possible hair colors.  For each person, a hair color id from that hair color list of values table would be stored in the person record.  So a traditional foreign key relationship.

Most of these drop downs are not huge they are small sets (10s of fields) so storing them in their own container within Cosmos seems like overkill.  I thought I could also set these values as constants in my API model and manage the values that way.  However if those values change I need to do a new build of the API in order to expose those values.

Any thoughts on  best practices for how to handle in the NoSQL space?  Create a container in the NoSQL backend with the list of values, store the values as constants within my API model or something else?

Appreciate your time considering this question.

答:
In these scenarios for reference data for UI elements I typically recommend storing all of this data in a single Cosmos container. Cosmos is schema agnostic so you can mix/match different schemas of data. If the data is <10GB use a dummy partition key (ie. /pk) with a single value and use a "type" property to distinguish among the different entity types for the data that match your UI elements. Fetch the data using a single query with the pk and then deserialize it into POCO's or whatever hydrates your UI using the type property to distinguish the different UI elements.

You can store this in a container that is part of a shared database. Minimum RU would be 100 RU/s with four containers in a database or 400 RU/s for dedicated container throughput. Which one you choose will depend on how much RU/s the query that fetches this data costs. You can easily get that by running the query in the Azure portal and looking at the query stats.


问:
linking a button to another page in SweetAlert
am i using sweet alert and i have 2 buttons; one is cancel button and the another one is continue button. i want to link the 'continue' button to another page that is 'trial.php'. how can i proceed with this? below is code i've tried:

if(m <= 2){
  swal({
    title:"dataset file is: "+  ""+size2 +"Mb",
    text: "a cluster of 1 node will be required for processing",
    buttons: {
      cancel: true,
      confirm: "continue"
    }
  })```

答:
Use .then() to watch the value of the pressed button and if the value is "continue", use window.location.href to redirect user to another page:

```<code>swal({
  title: "dataset file is: " + "" + size2 + "Mb",
  text: "a cluster of 1 node will be required for processing",
  buttons: {
    cancel: true,
    confirm: "continue"
  }
}).then((value) => {
  if (value === "continue") {
    window.location.href = "trial.php";
  }
});
</code>```

Body:
Use .then() to watch the value of the pressed button and if the value is "continue", use window.location.href to redirect user to another page:

swal({
  title: "dataset file is: " + "" + size2 + "Mb",
  text: "a cluster of 1 node will be required for processing",
  buttons: {
    cancel: true,
    confirm: "continue"
  }
}).then((value) => {
  if (value === "continue") {
    window.location.href = "trial.php";
  }
});


问:
wordpress: wp-graphql not working with custom post type
I've created a custom post type that is however not showing up in the GraphiQL explorer.

```<code>function create_custom_visions_post_type() {
       register_post_type('visions',
                  array(
                      'labels' => array(
                        'name' => __('Visions'),
                        'singular_name' => __('Visions')
                  ),
                    'public' => true,
                    'show_in_admin_bar' => true,
                    'show_in_graphql' => true,
                    'graphql_single_name' => 'Vision',
                    'graphql_plural_name' => 'Visions',
));
</code>```

}

According to the wp-graphql docs only the flags "show_in_graphql", 'graphql_single_name' and 'graphql_plural_name' are needed in order to expose a custom post type to the graphql schema.

What am i missing?

答:
Make sure you're registering your CPT before the WPGraphQL initializes the schema. You can do this by running your CPT registration code in the graphql_init hooks like this.

```<code>function create_custom_visions_post_type() {
       register_post_type('visions',
                  array(
                      'labels' => array(
                        'name' => __('Visions'),
                        'singular_name' => __('Visions')
                  ),
                    'public' => true,
                    'show_in_admin_bar' => true,
                    'show_in_graphql' => true,
                    'graphql_single_name' => 'Vision',
                    'graphql_plural_name' => 'Visions',
));
add_action( 'graphql_init', 'create_custom_visions_post_type' );
</code>```

Body:
I've created a custom post type that is however not showing up in the GraphiQL explorer.

function create_custom_visions_post_type() {
       register_post_type('visions',
                  array(
                      'labels' => array(
                        'name' => __('Visions'),
                        'singular_name' => __('Visions')
                  ),
                    'public' => true,
                    'show_in_admin_bar' => true,
                    'show_in_graphql' => true,
                    'graphql_single_name' => 'Vision',
                    'graphql_plural_name' => 'Visions',
));

}

According to the wp-graphql docs only the flags "show_in_graphql", 'graphql_single_name' and 'graphql_plural_name' are needed in order to expose a custom post type to the graphql schema.

What am i missing?

Body:
Make sure you're registering your CPT before the WPGraphQL initializes the schema. You can do this by running your CPT registration code in the graphql_init hooks like this.

function create_custom_visions_post_type() {
       register_post_type('visions',
                  array(
                      'labels' => array(
                        'name' => __('Visions'),
                        'singular_name' => __('Visions')
                  ),
                    'public' => true,
                    'show_in_admin_bar' => true,
                    'show_in_graphql' => true,
                    'graphql_single_name' => 'Vision',
                    'graphql_plural_name' => 'Visions',
));
add_action( 'graphql_init', 'create_custom_visions_post_type' );


问:
Touch Listener interferes with RecyclerView Scrolling
My app looks like this:

Basically a FrameLayout for hosting Fragments and Bottom Nav View. Now I would like to implement right swipe gesture in HomeFragment (when Home tab is selected). But that fragment hosts a RecyclerView. To add right swipe, I am using:

```<code>public class OnSwipeTouchListener implements View.OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener (Context ctx){
        gestureDetector = new GestureDetector(ctx, new GestureListener());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                        result = true;
                    }
                }
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom();
                    } else {
                        onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }
}
</code>```

When I add this touch listener to RecyclerView, scrolling doesn't happen smoothly. I don't know the reason behind this. Please explain if you have.

Now please suggest what should I do to overcome the issue. Is there any other way to set touch listener and gesture listener so that scrolling isn't hampered as well as I can detect swipe right gesture.

As a workaround, I tried setting a full transparent view above recyclerview and that detects gesture but recyclerview doesn't scroll.

答:
you can just change your FrameLayout with ViewPager, and add a listener for swipe action

change FrameLayout to ViewPager

```<code> <android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:layout_below="@id/tab_layout"/>
</code>```

Implement PagerAdapter

```<code>public class PagerAdapter extends FragmentStatePagerAdapter {
int fragmentNumber;

public PagerAdapter(FragmentManager fm, int fragmentNumber) {
    super(fm);
    this.fragmentNumber = fragmentNumber;
}

/**
 * Return the Fragment associated with a specified position.
 *
 * @param position
 */
@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            return new Fragment1();
        case 1:
            return new Fragment2();
        case 2:
            return new Fragment3();
        case 3:
            return new Fragment4();
        case 4:
            return new Fragment5();
        default:
            return null;
    }
}

/**
 * Return the number of views available.
 */
@Override
public int getCount() {
    return fragmentNumber;
}
}
</code>```

MainActivity Logic

```<code> @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ViewPager viewPager = findViewById(R.id.pager);
    final PagerAdapter adapter = new PagerAdapter
            (getSupportFragmentManager(), 5); //Change the number based on the number of Fragments you have
    viewPager.setAdapter(adapter);
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // put your scrolling logic here. use positionOffset and position to determine the next destination
        }

        @Override
        public void onPageSelected(int position) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
}
</code>```

you can also connect your viewPager with bottomNavigation for consistency
and these code can be impoved based on your specific case:kepping track of the non visible Fragments instead of distorying them .....

I hope this was helpfull.

Body:
My app looks like this:

Basically a FrameLayout for hosting Fragments and Bottom Nav View. Now I would like to implement right swipe gesture in HomeFragment (when Home tab is selected). But that fragment hosts a RecyclerView. To add right swipe, I am using:

public class OnSwipeTouchListener implements View.OnTouchListener {

    private final GestureDetector gestureDetector;

    public OnSwipeTouchListener (Context ctx){
        gestureDetector = new GestureDetector(ctx, new GestureListener());
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            onSwipeRight();
                        } else {
                            onSwipeLeft();
                        }
                        result = true;
                    }
                }
                else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        onSwipeBottom();
                    } else {
                        onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public void onSwipeRight() {
    }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }
}

When I add this touch listener to RecyclerView, scrolling doesn't happen smoothly. I don't know the reason behind this. Please explain if you have.

Now please suggest what should I do to overcome the issue. Is there any other way to set touch listener and gesture listener so that scrolling isn't hampered as well as I can detect swipe right gesture.

As a workaround, I tried setting a full transparent view above recyclerview and that detects gesture but recyclerview doesn't scroll.

Body:
you can just change your FrameLayout with ViewPager, and add a listener for swipe action

change FrameLayout to ViewPager

 <android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:layout_below="@id/tab_layout"/>

Implement PagerAdapter

public class PagerAdapter extends FragmentStatePagerAdapter {
int fragmentNumber;

public PagerAdapter(FragmentManager fm, int fragmentNumber) {
    super(fm);
    this.fragmentNumber = fragmentNumber;
}

/**
 * Return the Fragment associated with a specified position.
 *
 * @param position
 */
@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            return new Fragment1();
        case 1:
            return new Fragment2();
        case 2:
            return new Fragment3();
        case 3:
            return new Fragment4();
        case 4:
            return new Fragment5();
        default:
            return null;
    }
}

/**
 * Return the number of views available.
 */
@Override
public int getCount() {
    return fragmentNumber;
}
}

MainActivity Logic

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ViewPager viewPager = findViewById(R.id.pager);
    final PagerAdapter adapter = new PagerAdapter
            (getSupportFragmentManager(), 5); //Change the number based on the number of Fragments you have
    viewPager.setAdapter(adapter);
    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            // put your scrolling logic here. use positionOffset and position to determine the next destination
        }

        @Override
        public void onPageSelected(int position) {

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
}

you can also connect your viewPager with bottomNavigation for consistency
and these code can be impoved based on your specific case:kepping track of the non visible Fragments instead of distorying them .....

I hope this was helpfull.


问:
Async JavaScript: problem with undefined value
I have to write a function that receives a json, loops into it, takes some value from that to make an axios request to an api, takes some parameter from the api response and adds it to the json received in input. Here is the current code:

```<code>
let db_mock = require('../db_mock.json');

function Geolocation(db_mock: any): any {

    for (let i: number = 0; i < db_mock.length; i++) {

        if (db_mock[i].place == null) {
            console.log('ERRORE: Manca l\'indicazione del luogo');
            return;
        }

        for (let j: number = 0; j < db_mock[i].place.length; j++) {
            axios.get(URL)
            .then((response: any) => {
                db_mock[i].place[j] = {
                    city: response.data.Response.View[0].Result[0].Location.Address.City,
                    country: response.data.Response.View[0].Result[0].Location.Address.Country,
                    county: response.data.Response.View[0].Result[0].Location.Address.County,
                    label: response.data.Response.View[0].Result[0].Location.Address.Label,
                    postalCode: response.data.Response.View[0].Result[0].Location.Address.PostalCode,
                    state: response.data.Response.View[0].Result[0].Location.Address.State,
                    position: {
                        latitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Latitude,
                        longitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Longitude
                    }
                }
            })
            .catch((error: any) => console.log(error))
        }

    }

}

let db: any = Geolocation(db_mock);

// console.log(db);
</code>```

The problem is that when I try to get the modified json and console log it, it is undefined. I can't figure out how to handle this async object.

Any suggestions?

答:
I figured out how to solve the problem!

Here is my solution for those interested:

```<code>function Geolocation(db_mock: any) {

    const promises: any[] = [];

    return new Promise((resolve, reject) => {
        for (let i: number = 0; i < db_mock.length; i++) {

            if (db_mock[i].place == null) {
                reject(new Error("Manca l'indicazione del luogo"));
            }

            for (let j: number = 0; j < db_mock[i].place.length; j++) {
                promises.push(
                    axios.get(`https://geocoder.ls.hereapi.com/search/6.2/geocode.json?searchtext=${db_mock[i].place[j]}&apiKey=${process.env.API_KEY}`)
                    .then((response: any) => {
                        db_mock[i].place[j] = {
                            city: response.data.Response.View[0].Result[0].Location.Address.City,
                            country: response.data.Response.View[0].Result[0].Location.Address.Country,
                            county: response.data.Response.View[0].Result[0].Location.Address.County,
                            label: response.data.Response.View[0].Result[0].Location.Address.Label,
                            postalCode: response.data.Response.View[0].Result[0].Location.Address.PostalCode,
                            state: response.data.Response.View[0].Result[0].Location.Address.State,
                            position: {
                                latitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Latitude,
                                longitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Longitude
                            }
                        }
                    })
                    .catch((error: any) => reject(new Error(error)))
                )
            }

        }

        Promise.all(promises)
        .then(_ => resolve(db_mock) )
        .catch(err => reject(new Error(err)))
    })

}

Geolocation(db_mock)
.then(res => console.log(res))
.catch(err => console.log(err))
</code>```

Thanks to user Bergi for the help!

Body:
I have to write a function that receives a json, loops into it, takes some value from that to make an axios request to an api, takes some parameter from the api response and adds it to the json received in input. Here is the current code:

let db_mock = require('../db_mock.json');

function Geolocation(db_mock: any): any {

    for (let i: number = 0; i < db_mock.length; i++) {

        if (db_mock[i].place == null) {
            console.log('ERRORE: Manca l\'indicazione del luogo');
            return;
        }

        for (let j: number = 0; j < db_mock[i].place.length; j++) {
            axios.get(URL)
            .then((response: any) => {
                db_mock[i].place[j] = {
                    city: response.data.Response.View[0].Result[0].Location.Address.City,
                    country: response.data.Response.View[0].Result[0].Location.Address.Country,
                    county: response.data.Response.View[0].Result[0].Location.Address.County,
                    label: response.data.Response.View[0].Result[0].Location.Address.Label,
                    postalCode: response.data.Response.View[0].Result[0].Location.Address.PostalCode,
                    state: response.data.Response.View[0].Result[0].Location.Address.State,
                    position: {
                        latitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Latitude,
                        longitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Longitude
                    }
                }
            })
            .catch((error: any) => console.log(error))
        }

    }

}

let db: any = Geolocation(db_mock);

// console.log(db);

The problem is that when I try to get the modified json and console log it, it is undefined. I can't figure out how to handle this async object.

Any suggestions?

Body:
I figured out how to solve the problem!

Here is my solution for those interested:

function Geolocation(db_mock: any) {

    const promises: any[] = [];

    return new Promise((resolve, reject) => {
        for (let i: number = 0; i < db_mock.length; i++) {

            if (db_mock[i].place == null) {
                reject(new Error("Manca l'indicazione del luogo"));
            }

            for (let j: number = 0; j < db_mock[i].place.length; j++) {
                promises.push(
                    axios.get(`https://geocoder.ls.hereapi.com/search/6.2/geocode.json?searchtext=${db_mock[i].place[j]}&apiKey=${process.env.API_KEY}`)
                    .then((response: any) => {
                        db_mock[i].place[j] = {
                            city: response.data.Response.View[0].Result[0].Location.Address.City,
                            country: response.data.Response.View[0].Result[0].Location.Address.Country,
                            county: response.data.Response.View[0].Result[0].Location.Address.County,
                            label: response.data.Response.View[0].Result[0].Location.Address.Label,
                            postalCode: response.data.Response.View[0].Result[0].Location.Address.PostalCode,
                            state: response.data.Response.View[0].Result[0].Location.Address.State,
                            position: {
                                latitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Latitude,
                                longitude: response.data.Response.View[0].Result[0].Location.DisplayPosition.Longitude
                            }
                        }
                    })
                    .catch((error: any) => reject(new Error(error)))
                )
            }

        }

        Promise.all(promises)
        .then(_ => resolve(db_mock) )
        .catch(err => reject(new Error(err)))
    })

}

Geolocation(db_mock)
.then(res => console.log(res))
.catch(err => console.log(err))

Thanks to user Bergi for the help!


问:
issue with my main method in my connect4 game
Im having a problem with my main method, whenevr I run it my code cant compile because of this problem :
"Exception in thread "main" java.lang.NullPointerException
    at UI.ConnectFourFrame.refreshUI(ConnectFourFrame.java:96)
    at UI.ConnectFourFrame.(ConnectFourFrame.java:43)
    at main.main(main.java:11)"

I am trying to see what the issue is but I cant figure it out, can someone help me

```<code>package Game;

import java.util.ArrayList;

public class ConnectFourBoard {

    // This constant is used to indicate the width and height, in cells,
    // of the board.  Since we want an 8x8 board, we'll set it to 8.
    private static final int WIDTH = 7;
    private static final int HEIGHT = 6;
    private ConnectFourCell[][] currentPlayer;

    // The current state the Othello board is defined with these two
    // fields: a two-dimensional array holding the state of each cell,
    // and a boolean value indicating whether it's the black player's
    // turn (true) or the white player's turn (false).
    private ConnectFourCell[][] cells;
    private boolean isBlueTurn;

    // Since the board is a model and it needs to notify views of changes,
    // it will employ the standard "listener" mechanism of tracking a list
    // of listeners and firing "events" (by calling methods on those
    // listeners) when things change.
    private ArrayList<ConnectFourListener> listeners;

    public ConnectFourBoard()
    {
        // Arrays, in Java, are objects, which means that variables of
        // array types (like cells, which has type OthelloCell[][]) are
        // really references that say where an array lives.  By default,
        // references point to null.  So we'll need to create an actual
        // two-dimensional array for "cells" to point to.
        cells = new ConnectFourCell[WIDTH][HEIGHT];
        listeners = new ArrayList<ConnectFourListener>();
        reset();
    }

    public void reset(){
        for (int i = 0; i<WIDTH ; i++){
            for (int j = 0; j<HEIGHT; j++){

                cells[i][j] = ConnectFourCell.NONE;
            }
        }

        isBlueTurn = true;
    }

    public void addConnectFourListener(ConnectFourListener listener)
    {
        listeners.add(listener);
    }

    public void removeConnectFourListener(ConnectFourListener listener)
    {
        if (listeners.contains(listener))
        {
            listeners.remove(listener);
        }
    }

    // These are fairly standard "fire event" methods that we've been building
    // all quarter, one corresponding to each method in the listener interface.

    private void fireBoardChanged()
    {
        for (ConnectFourListener listener : listeners)
        {
            listener.boardChanged();
        }
    }

    private void fireGameOver()
    {
        for (ConnectFourListener listener : listeners)
        {
            listener.gameOver();
        }
    }

    // isBlackTurn() returns true if it's the black player's turn, and false
    // if it's the white player's turn.
    public boolean isBlueTurn()
    {
        return isBlueTurn;
    }

    public int getWidth()
    {
        return WIDTH;

    }

    public int getHeight(){

        return HEIGHT;
    }
    // getBlackScore() calculates the score for the black player.
    public int getBlackScore()
    {
        return getScore(ConnectFourCell.BLUE);
    }

    // getWhiteScore() calculates the score for the white player.
    public int getWhiteScore()
    {
        return getScore(ConnectFourCell.RED);
    }

    // getScore() runs through all the cells on the board and counts the
    // number of cells that have a particular value (e.g., BLACK or WHITE).
    // This method uses the naive approach of counting them each time
    // it's called; it might be better to keep track of this score as we
    // go, updating it as tiles are added and flipped.
    private int getScore(ConnectFourCell cellValue)
    {
        int score = 0;

        for (int i = 0; i < WIDTH; i++)
        {
            for (int j = 0; j < HEIGHT; j++)
            {
                if (cells[i][j] == cellValue)
                {
                    score++;
                }
            }
        }

        return score;
    }

    // getWhiteScore() calculates the score for the white player.
    public int getRedScore()
    {
        return getScore(ConnectFourCell.RED);
    }

    public int getBlueScore() {
        // TODO Auto-generated method stub
        return getScore(ConnectFourCell.BLUE);
    }

    public ConnectFourCell getCell(int x, int y)
    {
        if (!isValidCell(x, y))
        {
            throw new IllegalArgumentException(
                "(" + x + ", " + y + ") is not a valid cell");
        }

        return cells[x][y];
    }
    /**
    * The drop method.
    *
    * Drop a checker into the specified HEIGHT,
    * and return the WIDTH that the checker lands on.
    */
    int drop(int HEIGHT) {
    if (hasWon()) {
    return -1;
    }

    for ( ; WIDTH<6 && HEIGHT != 0; WIDTH++) { };

    if (WIDTH==6) {
    // if the WIDTH is 6, it went through all 6 WIDTHs
    // of the cells, and couldn't find an empty one.
    // Therefore, return false to indicate that this
    // drop operation failed.
    return -1;
    }
    // fill the WIDTH of that HEIGHT with a checker.
    cells[HEIGHT][WIDTH] = currentPlayer[HEIGHT][WIDTH];
    // alternate the players
    //currentPlayer = (currentPlayer%2)+1;
    return WIDTH;
    }
    /**
    * The toString method
    *
    * Returns a String representation of this
    * Connect Four (TM) game.
    */
    public String toString() {
    String returnString = "";
    for (int WIDTH=5; WIDTH>=0; WIDTH--) {
    for (int HEIGHT=0; HEIGHT<7; HEIGHT++) {
    returnString = returnString + cells[HEIGHT][WIDTH];
    }
    returnString = returnString + "\n";
    }
    return returnString;
    }
    /**
    * The hasWon method.
    *
    * This method returns true if one of the
    * players has won the game.
    */
    public boolean hasWon() {
    boolean status = false;
    // check for a horizontal win
    for (int WIDTH=0; WIDTH<6; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
    if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE)  &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH]) {
    status = true;
    }
    }
    }
    // check for a vertical win
    for (int WIDTH=0; WIDTH<3; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<7; HEIGHT++) {
    if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE)  &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+1] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+2] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+3]) {
    status = true;
    }
    }
    }
    // check for a diagonal win (positive slope)
    for (int WIDTH=0; WIDTH<3; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
        if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE) &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH+1] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH+2] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH+3]) {
    status = true;
    }
    }
    }
    // check for a diagonal win (negative slope)
    for (int WIDTH=3; WIDTH<6; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
        if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE)  &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH-1] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH-2] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH-3]) {
    status = true;
    }
    }
    }
    return status;
    }

    private boolean isValidCell(int x, int y)
    {
        return x >= 0 && x < WIDTH
              && x>= 0 && x<HEIGHT
              && y >= 0 && y < WIDTH
              && y>= 0 && y<HEIGHT;
    }
}

package UI;

import java.awt.*;

import javax.swing.*;

import UI.ConnectFourBoardPanel;

import Game.ConnectFourBoard;
import Game.ConnectFourListener;

public class ConnectFourFrame extends JFrame implements ConnectFourListener {

    // Variables

    private ConnectFourBoard board;

    private JLabel scoreLabel;
    private ConnectFourBoardPanel boardPanel;
    private JLabel statusLabel;

    public ConnectFourFrame()
    {
        // The frame builds its own model.
        ConnectFourBoard board = new ConnectFourBoard();

        // We want the frame to receive notifications from the board as its
        // state changes.
        System.out.println(this);
        board.addConnectFourListener(this);

        setTitle("Informatics 45 Spring 2011: ConnectFour Game");
        setSize(700, 700);
        setResizable(true);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        getContentPane().setBackground(Color.BLACK);

        buildUI();
        refreshUI();
    }

    private void buildUI()
    {
        GridBagLayout layout = new GridBagLayout();
        getContentPane().setLayout(layout);

        Font labelFont = new Font("SansSerif", Font.BOLD, 18);

        scoreLabel = new JLabel();
        scoreLabel.setForeground(Color.WHITE);
        scoreLabel.setFont(labelFont);
        layout.setConstraints(
            scoreLabel,
            new GridBagConstraints(
                0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.CENTER,
                GridBagConstraints.NONE,
                new Insets(10, 10, 10, 10), 0, 0));
        getContentPane().add(scoreLabel);

        boardPanel = new ConnectFourBoardPanel(board);
        layout.setConstraints(
            boardPanel,
            new GridBagConstraints(
                0, 1, 1, 1, 1.0, 1.0,
                GridBagConstraints.CENTER,
                GridBagConstraints.BOTH,
                new Insets(10, 10, 10, 10), 0, 0));
        getContentPane().add(boardPanel);

        statusLabel = new JLabel();
        statusLabel.setForeground(Color.WHITE);
        statusLabel.setFont(labelFont);
        layout.setConstraints(
            statusLabel,
            new GridBagConstraints(
                0, 2, 1, 1, 1.0, 0.0,
                GridBagConstraints.CENTER,
                GridBagConstraints.NONE,
                new Insets(10, 10, 10, 10), 0, 0));
        getContentPane().add(statusLabel);
    }

    private void refreshUI()
    {
        // Refreshing the UI means to change the text in each of the
        // two labels (the score and the status) and also to ask the
        // board to repaint itself.

        scoreLabel.setText(
            "Blue: " + board.getBlueScore() +
            "          Red: " + board.getRedScore());

        statusLabel.setText(
            (board.isBlueTurn() ? "Blue's" : "Red's")
            + " turn");

        boardPanel.repaint();
    }

    // These are the ConnectFourBoardListener event-handling methods.

    public void boardChanged()
    {
        // When the board changes, we'll refresh the entire UI.  (There
        // are times when this approach is too inefficient, but it will
        // work fine for our relatively simple UI.)

        refreshUI();
    }

    public void gameOver()
    {
        // When the game is over, we'll pop up a message box showing the final
        // score, then, after the user dismisses the message box, dispose of
        // this window and end the program.

        JOptionPane.showMessageDialog(
            this,
            "Game over!\nFinal score: " + scoreLabel.getText(),
            "Game Over",
            JOptionPane.INFORMATION_MESSAGE);

        dispose();
    }

}
</code>```

答:
your initialising a local var instead of your member var

```<code>    ConnectFourBoard board = new ConnectFourBoard();
</code>```

change that line to:

```<code>    board = new ConnectFourBoard();
</code>```

Body:
Im having a problem with my main method, whenevr I run it my code cant compile because of this problem :
"Exception in thread "main" java.lang.NullPointerException
    at UI.ConnectFourFrame.refreshUI(ConnectFourFrame.java:96)
    at UI.ConnectFourFrame.(ConnectFourFrame.java:43)
    at main.main(main.java:11)"

I am trying to see what the issue is but I cant figure it out, can someone help me

package Game;

import java.util.ArrayList;

public class ConnectFourBoard {

    // This constant is used to indicate the width and height, in cells,
    // of the board.  Since we want an 8x8 board, we'll set it to 8.
    private static final int WIDTH = 7;
    private static final int HEIGHT = 6;
    private ConnectFourCell[][] currentPlayer;

    // The current state the Othello board is defined with these two
    // fields: a two-dimensional array holding the state of each cell,
    // and a boolean value indicating whether it's the black player's
    // turn (true) or the white player's turn (false).
    private ConnectFourCell[][] cells;
    private boolean isBlueTurn;

    // Since the board is a model and it needs to notify views of changes,
    // it will employ the standard "listener" mechanism of tracking a list
    // of listeners and firing "events" (by calling methods on those
    // listeners) when things change.
    private ArrayList<ConnectFourListener> listeners;

    public ConnectFourBoard()
    {
        // Arrays, in Java, are objects, which means that variables of
        // array types (like cells, which has type OthelloCell[][]) are
        // really references that say where an array lives.  By default,
        // references point to null.  So we'll need to create an actual
        // two-dimensional array for "cells" to point to.
        cells = new ConnectFourCell[WIDTH][HEIGHT];
        listeners = new ArrayList<ConnectFourListener>();
        reset();
    }

    public void reset(){
        for (int i = 0; i<WIDTH ; i++){
            for (int j = 0; j<HEIGHT; j++){

                cells[i][j] = ConnectFourCell.NONE;
            }
        }

        isBlueTurn = true;
    }

    public void addConnectFourListener(ConnectFourListener listener)
    {
        listeners.add(listener);
    }

    public void removeConnectFourListener(ConnectFourListener listener)
    {
        if (listeners.contains(listener))
        {
            listeners.remove(listener);
        }
    }

    // These are fairly standard "fire event" methods that we've been building
    // all quarter, one corresponding to each method in the listener interface.

    private void fireBoardChanged()
    {
        for (ConnectFourListener listener : listeners)
        {
            listener.boardChanged();
        }
    }

    private void fireGameOver()
    {
        for (ConnectFourListener listener : listeners)
        {
            listener.gameOver();
        }
    }

    // isBlackTurn() returns true if it's the black player's turn, and false
    // if it's the white player's turn.
    public boolean isBlueTurn()
    {
        return isBlueTurn;
    }

    public int getWidth()
    {
        return WIDTH;

    }

    public int getHeight(){

        return HEIGHT;
    }
    // getBlackScore() calculates the score for the black player.
    public int getBlackScore()
    {
        return getScore(ConnectFourCell.BLUE);
    }

    // getWhiteScore() calculates the score for the white player.
    public int getWhiteScore()
    {
        return getScore(ConnectFourCell.RED);
    }

    // getScore() runs through all the cells on the board and counts the
    // number of cells that have a particular value (e.g., BLACK or WHITE).
    // This method uses the naive approach of counting them each time
    // it's called; it might be better to keep track of this score as we
    // go, updating it as tiles are added and flipped.
    private int getScore(ConnectFourCell cellValue)
    {
        int score = 0;

        for (int i = 0; i < WIDTH; i++)
        {
            for (int j = 0; j < HEIGHT; j++)
            {
                if (cells[i][j] == cellValue)
                {
                    score++;
                }
            }
        }

        return score;
    }

    // getWhiteScore() calculates the score for the white player.
    public int getRedScore()
    {
        return getScore(ConnectFourCell.RED);
    }

    public int getBlueScore() {
        // TODO Auto-generated method stub
        return getScore(ConnectFourCell.BLUE);
    }

    public ConnectFourCell getCell(int x, int y)
    {
        if (!isValidCell(x, y))
        {
            throw new IllegalArgumentException(
                "(" + x + ", " + y + ") is not a valid cell");
        }

        return cells[x][y];
    }
    /**
    * The drop method.
    *
    * Drop a checker into the specified HEIGHT,
    * and return the WIDTH that the checker lands on.
    */
    int drop(int HEIGHT) {
    if (hasWon()) {
    return -1;
    }

    for ( ; WIDTH<6 && HEIGHT != 0; WIDTH++) { };

    if (WIDTH==6) {
    // if the WIDTH is 6, it went through all 6 WIDTHs
    // of the cells, and couldn't find an empty one.
    // Therefore, return false to indicate that this
    // drop operation failed.
    return -1;
    }
    // fill the WIDTH of that HEIGHT with a checker.
    cells[HEIGHT][WIDTH] = currentPlayer[HEIGHT][WIDTH];
    // alternate the players
    //currentPlayer = (currentPlayer%2)+1;
    return WIDTH;
    }
    /**
    * The toString method
    *
    * Returns a String representation of this
    * Connect Four (TM) game.
    */
    public String toString() {
    String returnString = "";
    for (int WIDTH=5; WIDTH>=0; WIDTH--) {
    for (int HEIGHT=0; HEIGHT<7; HEIGHT++) {
    returnString = returnString + cells[HEIGHT][WIDTH];
    }
    returnString = returnString + "\n";
    }
    return returnString;
    }
    /**
    * The hasWon method.
    *
    * This method returns true if one of the
    * players has won the game.
    */
    public boolean hasWon() {
    boolean status = false;
    // check for a horizontal win
    for (int WIDTH=0; WIDTH<6; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
    if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE)  &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH]) {
    status = true;
    }
    }
    }
    // check for a vertical win
    for (int WIDTH=0; WIDTH<3; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<7; HEIGHT++) {
    if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE)  &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+1] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+2] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT][WIDTH+3]) {
    status = true;
    }
    }
    }
    // check for a diagonal win (positive slope)
    for (int WIDTH=0; WIDTH<3; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
        if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE) &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH+1] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH+2] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH+3]) {
    status = true;
    }
    }
    }
    // check for a diagonal win (negative slope)
    for (int WIDTH=3; WIDTH<6; WIDTH++) {
    for (int HEIGHT=0; HEIGHT<4; HEIGHT++) {
        if (!(cells[HEIGHT][WIDTH] == ConnectFourCell.NONE)  &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+1][WIDTH-1] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+2][WIDTH-2] &&
    cells[HEIGHT][WIDTH] == cells[HEIGHT+3][WIDTH-3]) {
    status = true;
    }
    }
    }
    return status;
    }

    private boolean isValidCell(int x, int y)
    {
        return x >= 0 && x < WIDTH
              && x>= 0 && x<HEIGHT
              && y >= 0 && y < WIDTH
              && y>= 0 && y<HEIGHT;
    }
}

package UI;

import java.awt.*;

import javax.swing.*;

import UI.ConnectFourBoardPanel;

import Game.ConnectFourBoard;
import Game.ConnectFourListener;

public class ConnectFourFrame extends JFrame implements ConnectFourListener {

    // Variables

    private ConnectFourBoard board;

    private JLabel scoreLabel;
    private ConnectFourBoardPanel boardPanel;
    private JLabel statusLabel;

    public ConnectFourFrame()
    {
        // The frame builds its own model.
        ConnectFourBoard board = new ConnectFourBoard();

        // We want the frame to receive notifications from the board as its
        // state changes.
        System.out.println(this);
        board.addConnectFourListener(this);

        setTitle("Informatics 45 Spring 2011: ConnectFour Game");
        setSize(700, 700);
        setResizable(true);
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        getContentPane().setBackground(Color.BLACK);

        buildUI();
        refreshUI();
    }

    private void buildUI()
    {
        GridBagLayout layout = new GridBagLayout();
        getContentPane().setLayout(layout);

        Font labelFont = new Font("SansSerif", Font.BOLD, 18);

        scoreLabel = new JLabel();
        scoreLabel.setForeground(Color.WHITE);
        scoreLabel.setFont(labelFont);
        layout.setConstraints(
            scoreLabel,
            new GridBagConstraints(
                0, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.CENTER,
                GridBagConstraints.NONE,
                new Insets(10, 10, 10, 10), 0, 0));
        getContentPane().add(scoreLabel);

        boardPanel = new ConnectFourBoardPanel(board);
        layout.setConstraints(
            boardPanel,
            new GridBagConstraints(
                0, 1, 1, 1, 1.0, 1.0,
                GridBagConstraints.CENTER,
                GridBagConstraints.BOTH,
                new Insets(10, 10, 10, 10), 0, 0));
        getContentPane().add(boardPanel);

        statusLabel = new JLabel();
        statusLabel.setForeground(Color.WHITE);
        statusLabel.setFont(labelFont);
        layout.setConstraints(
            statusLabel,
            new GridBagConstraints(
                0, 2, 1, 1, 1.0, 0.0,
                GridBagConstraints.CENTER,
                GridBagConstraints.NONE,
                new Insets(10, 10, 10, 10), 0, 0));
        getContentPane().add(statusLabel);
    }

    private void refreshUI()
    {
        // Refreshing the UI means to change the text in each of the
        // two labels (the score and the status) and also to ask the
        // board to repaint itself.

        scoreLabel.setText(
            "Blue: " + board.getBlueScore() +
            "          Red: " + board.getRedScore());

        statusLabel.setText(
            (board.isBlueTurn() ? "Blue's" : "Red's")
            + " turn");

        boardPanel.repaint();
    }

    // These are the ConnectFourBoardListener event-handling methods.

    public void boardChanged()
    {
        // When the board changes, we'll refresh the entire UI.  (There
        // are times when this approach is too inefficient, but it will
        // work fine for our relatively simple UI.)

        refreshUI();
    }

    public void gameOver()
    {
        // When the game is over, we'll pop up a message box showing the final
        // score, then, after the user dismisses the message box, dispose of
        // this window and end the program.

        JOptionPane.showMessageDialog(
            this,
            "Game over!\nFinal score: " + scoreLabel.getText(),
            "Game Over",
            JOptionPane.INFORMATION_MESSAGE);

        dispose();
    }

}

Body:
your initialising a local var instead of your member var

    ConnectFourBoard board = new ConnectFourBoard();

change that line to:

    board = new ConnectFourBoard();


问:
While importing train_test_split from from sklearn.model_selection, why am I getting the error "AttributeError: module 'attr' has no attribute 's'"?
```<code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn
from sklearn.model_selection import train_test_split
import statsmodels.api as sm
</code>```

While running this cell in Jupyter Notebook I am getting the following error:

```<code>C:\Anaconda\lib\site-packages\_pytest\_code\__init__.py in <module>
      1 """ python inspection/code generation API """
----> 2 from .code import Code  # noqa
      3 from .code import ExceptionInfo  # noqa
      4 from .code import filter_traceback  # noqa
      5 from .code import Frame  # noqa

C:\Anaconda\lib\site-packages\_pytest\_code\code.py in <module>
    390
    391
--> 392 @attr.s(repr=False)
    393 class ExceptionInfo(Generic[_E]):
    394     """ wraps sys.exc_info() objects and offers

AttributeError: module 'attr' has no attribute 's'
</code>```

Can somebody explain what is happening?

答:
Enter these commands on the terminal or in a notebook:</p>
```<code>pip uninstall attr
pip install attrs
</code>```

Body:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn
from sklearn.model_selection import train_test_split
import statsmodels.api as sm

While running this cell in Jupyter Notebook I am getting the following error:

C:\Anaconda\lib\site-packages\_pytest\_code\__init__.py in <module>
      1 """ python inspection/code generation API """
----> 2 from .code import Code  # noqa
      3 from .code import ExceptionInfo  # noqa
      4 from .code import filter_traceback  # noqa
      5 from .code import Frame  # noqa

C:\Anaconda\lib\site-packages\_pytest\_code\code.py in <module>
    390
    391
--> 392 @attr.s(repr=False)
    393 class ExceptionInfo(Generic[_E]):
    394     """ wraps sys.exc_info() objects and offers

AttributeError: module 'attr' has no attribute 's'

Can somebody explain what is happening?

Body:
Enter these commands on the terminal or in a notebook:

pip uninstall attr
pip install attrs


问:
Using Durable Functions, how to return multiple values from an Activity Functions
I’m a big Domain Driven Design fan and developer, and am always attempting to map technology/architecture into the world of DDD. Mapping microservices to bounded contexts provides for a natural marriage. At the end of the day, I just want to focus on my business logic and host that in the right environment. Durable Functions looked promising to me, in needing to solve the distributed transaction problem across microservices, Sagas or Process Manager if you will. I have been using NServicebus for years, and love their Saga technology, but would like to leverage Durable Function orchestrations for handling saga logic.

The architecture problem that I am currently having is the following. I have mapped the DDD Application Service to an Activity Function. A Saga would therefore be created simply with an Orchestrator tapping the right set of Activity Functions to run their transactions. Building out a rollback is pretty straightforward as well conceptually, but I am having an implementation problem. As an aside, each Activity Function will delegate to a library that handles all the business logic details, and will then take the list of events returned by the business logic and return that back to the Orchestrator. As far as I have researched, there is no way to return a polymorphic return value from an Activity Function. So if my business logic generates either a UpdateSucceeded or a UpdateFailed event, how would I simply return that from my Activity Function back to the Orchestrator so that the Orchestrator can take corrective action by calling distinct rollback Activity Functions?</p>

答: Sure, adding serialization code before and after call would work, but sub optimal. The activity function signature would lose its type specificity. Workable, but not very elegant.</p>