问:
How to implement an action listener with generic enums?
I am in the process of refactoring my application and my teacher recommended that I replace the GUI builder generated code with a more generic one.

Right now every JMenuItem has its own action listener. What I'm trying to achieve is a sort of generic control function for every menu item by using  enums in a single action listener. The code below should give you a general idea. clE is the enum key and I believe the enum should implement an interface for reading its label.

I've been doing a bit of research and I'm sure it's something simple, but I can't get fully grasp it yet. Thanks in advance!

```<code>public class JECheckBox<E extends ENUM_Label_INTF<?>> extends JCheckBox {

     private final E clE;

     // +++++++ CONSTRUCTOR +++++++++
     public JECheckBox(final E clE) {
         super( ((GetLabelINTF) clE).GetLabel() );
         this.clE = clE;
     }

     public E GetKey() {
         return clE;
     }
}
</code>```

答: Not suew what you mean by generic enums. Try giving every menu item (or any component) it's own name using component.setName(SomeEnum.soneValue.toString()). Then get the name in the action listener and do a switch(SomeEnum.valueOf(name).</p>

Body:
I am in the process of refactoring my application and my teacher recommended that I replace the GUI builder generated code with a more generic one.

Right now every JMenuItem has its own action listener. What I'm trying to achieve is a sort of generic control function for every menu item by using  enums in a single action listener. The code below should give you a general idea. clE is the enum key and I believe the enum should implement an interface for reading its label.

I've been doing a bit of research and I'm sure it's something simple, but I can't get fully grasp it yet. Thanks in advance!

public class JECheckBox<E extends ENUM_Label_INTF<?>> extends JCheckBox {

     private final E clE;

     // +++++++ CONSTRUCTOR +++++++++
     public JECheckBox(final E clE) {
         super( ((GetLabelINTF) clE).GetLabel() );
         this.clE = clE;
     }

     public E GetKey() {
         return clE;
     }
}


来源: stackexchange

问:
Trying to connect to a grpc service, running on an isolated Docker swarm, that is exposed through Traefik
I have been trying to configure Traefik to be the reverse proxy for my dev docker swarm which runs on its own VPN, isolated from the outer world.
The swarm consists of 3 manager nodes and 3 worker nodes and it does not have any TLS for communication between them.
I have managed to properly set a number of frontends (with rules for Host) and backends that point to services running in the swarm.
Below, is my docker-compose file which I use to deploy the docker stack for traefik on the swarm.

```<code>version: '3.6'

networks:
  traefik:
    driver: overlay

configs:
  traefik:
    file: ./config.dev.toml

services:
  traefik:
    image: traefik:1.7
    command:
      - --docker
      - --docker.swarmMode
      - --docker.domain=traefik.dev.pap
      - --docker.exposedByDefault=false
      - --entryPoints=Name:http Address::80 Redirect.EntryPoint:https
      - --entryPoints=Name:https Address::443 TLS:/certs/certfile.cert,/certs/keyfile.key
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    configs:
      - source: traefik
        target: /traefik.toml
    networks:
      - traefik
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
      - target: 8080
        published: 8080
        mode: host
      - target: 8081
        published: 8081
        mode: host
      - target: 8082
        published: 8082
        mode: host
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
</code>```

Toml file for traefik

```<code>defaultEntryPoints = ["http", "https"]

logLevel = "WARN"

insecureSkipVerify = true

[entryPoints]
  [entryPoints.http]
    address = ":80"
    [entryPoints.http.auth.basic]
    users = ["traefik:$2y$05$ZF08gDSv0f88vEUVzmwuxu.9seYIAZVzTMXnrETBDhQT30dxu4vOu"]
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = """-----BEGIN CERTIFICATE-----
                    MIICsjCCAZoCCQDP9WReX5fgQjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBAq
                    dHJhZWZpay5kZXYucGFwMB4XDTE5MDUyNDIwMTYzMloXDTIwMDUyMzIwMTYzMlow
                    GzEZMBcGA1UEAwwQKnRyYWVmaWsuZGV2LnBhcDCCASIwDQYJKoZIhvcNAQEBBQAD
                    ggEPADCCAQoCggEBAJ86nJMpyENKQrsDlfrMI8TwdAuHXXLpglMSPVmmTzm0Y7F7
                    CVRAwl8NJdbBJnBmK3+vaG1P3WfXfu/pBfn8GDrvlJd+1XqKdExMYMCDy2Ay1ghk
                    1mOcRkJ2XS2h7FjvGjAmE7/icYZprRziek/4hLCtpTjPwPIx/5tN/ZR+lpMXe+dG
                    24CqvcTftZCS+RZSMuACG0tKlmhOx/xjoUOQMiEA8ysmQE+RrEs7ZSvu1SLYMILa
                    jGrHmH/52kIia+zOJqi8k4pVTkRFB1CNeSURgFOQf1zWzSI49GTh0UGsmlgeMoOX
                    FgrEjsbmMKxCz8ItPiTMjJ1zLd5YyBt+ATeDl0kCAwEAATANBgkqhkiG9w0BAQsF
                    AAOCAQEAYXrBbyJ75TMInYmPjkPD/Vdh3dI62qwHrKJsXN519FC8gbYSJFSdr5Pd
                    y/stM2Xn8KGgnkLSuo62MzGD15X/IYqn4Kt9Eizqd5kpsdNc7l/pTTidcCY3nQ82
                    CUGQrnwyVjZ/8wwbjtTL1TOismK3yA169WXD2yXGz15fR08lLCMqXEKotl82FxfX
                    6mw9EkLC3MAfIxuuWcaCl8/AHAUlrzrQOoVj9OkBcxwYeYH++KKYOGCaiuKMen9x
                    cjyCo05qmBQq4PWOoafDJMrdAcnzjc0tTW3DBTnJY7tR0qA/6iGVsdlHce6rMZtR
                    sb5m6XFgABCcg54yfrHIGgv1Te78aA==
                    -----END CERTIFICATE-----
                    """
      keyFile = """-----BEGIN PRIVATE KEY-----
                    MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCfOpyTKchDSkK7
                    A5X6zCPE8HQLh11y6YJTEj1Zpk85tGOxewlUQMJfDSXWwSZwZit/r2htT91n137v
                    6QX5/Bg675SXftV6inRMTGDAg8tgMtYIZNZjnEZCdl0toexY7xowJhO/4nGGaa0c
                    4npP+ISwraU4z8DyMf+bTf2UfpaTF3vnRtuAqr3E37WQkvkWUjLgAhtLSpZoTsf8
                    Y6FDkDIhAPMrJkBPkaxLO2Ur7tUi2DCC2oxqx5h/+dpCImvsziaovJOKVU5ERQdQ
                    jXklEYBTkH9c1s0iOPRk4dFBrJpYHjKDlxYKxI7G5jCsQs/CLT4kzIydcy3eWMgb
                    fgE3g5dJAgMBAAECggEBAJb3QyxkGPNznQEizTgUBHXcZKnplbg1nNKWIIS3IbZc
                    SYkkVhwDqkXkeVO7nW5D8EoHTMMXTZv+vONJ09jII1D9hax9HHoqe0k7wR/F1TVH
                    /ZXHxVx79kFdZ8q0Exne2L193Iu5blk6KF+SetUHkwbQHC5ZC16V+PqOXzZDLxAV
                    XOXjv5nOK2bqffgZdjYmW3fiwARJ1y/2s6G2Pn3Uk9z3Hk259ZI6k1zE4mwmf62t
                    FQJfjDQ7Ej7N0lXwmSA/Kb7qTXQ/div+juGlEjKTZIZRJMcLOxaZMo93sU8T/Y6b
                    wWnsRvEZlZ9yy8Y/OWN3UxWjc6nx8DPI6sYnTBUNEmECgYEA0Co6Px6n4CFtmeT6
                    6vj/YNGY1vzrycqixtymaIJk7TmPXeLqL919Sro/jbI0B189tnm3DFLk458feRaA
                    Nw+Jl1vQo9IjutJ1ujNt7IrCtlP6smRpQ5fXQ9Ywk3IPtZiG9W+fxM1uHSYKoAh/
                    sAym38Ao5hPRoRJ0TJxvlkCJtz8CgYEAw9GdFa+CXcx9U8pZE1tV2J9gXjd0mr10
                    OKjpKA9ez8IOB9S96bNOiEwHzzsza+OFoou1DrIK0zoK2+XYZYJ+sWOU1pO4PYlj
                    vbRC5kFb2EvD5h47oIoAWqk3QOGewM+z6eWI9r4LTOgdiZ1r6c73jydGGtTBtcZq
                    oqgVOziHV3cCgYEAgtw495se77A0BU3ES1iyujuo+GXRGG7xe1AUsJhgOB06Okw+
                    6k4zyHljIIGJYaUG16KWZwHpcAqFL4rsmTCET4lhlMqyuWw6pA5WqR/mHdaXP/QN
                    lHds1PFeYiKPK5qyJLLCXmbCNULH5SjSlGqvsPNNAq4s1zQRtmOVZoA10uMCgYBw
                    laPrQ+2AYIHuGvj72BeTZI7TnK6+CQ85RGRJVAz/BmNqvTYzl5QfaRdUXoVCEp5S
                    xmBjApqWt1hm9c9lDZIqC0cX1/al6sgd2fZczFcyFN2dAOTneHCbr47FDvNniAO5
                    Bu+obbuxjALvjELvOr+63qm/43M8P8gvnNQYKHgoIQKBgQCQJrT3z27O/hRVUIGg
                    bwAmzwGExOC39uLHNWmOcVmw36oV592sVw1K9pRvPFVJp956T63lhcGv4t0ki2DE
                    gBN/V1jhkAw33qRDd5bbYmIutf6RO7HeewwFHpbaLw0FULe5UlsziE9AbTHmddqU
                    GTcyajXnqimXvSu6AC9XFA9s4g==
                    -----END PRIVATE KEY-----
                   """
  [entryPoints.api]
    address = ":8081"
  [entryPoints.ping]
    address = ":8082"

[api]
  entryPoint = "api"
  dashboard = true

[ping]
  entryPoint = "ping"

[retry]
  logLevel = "DEBUG"

[traefikLog]
  logLevel = "DEBUG"
  format   = "json"

[accessLog]
  logLevel = "DEBUG"
  format = "json"

[docker]
  endpoint = "unix:///var/run/docker.sock"
  domain = "traefik.dev.pbp"
  swarmmode = true
  watch = true
  exposedByDefault = false
</code>```

The certificates above were generated on my laptop with the command:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./backend.key -out ./backend.cert and Common Name:*traefik.dev.pap.

The 2 services I want to expose have the following labels:

```<code>      labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_traefik"
      # Public segment
      - "traefik.public.protocol=h2c"
      - "traefik.public.port=50051"
      - "traefik.public.frontend.rule=Host:serviceA-grpc.traefik.dev.pbp"
      - "traefik.public.frontend.auth.forward.tls.insecureSkipVerify=true"
      - "traefik.public.backend.loadbalancer.method=drr"
      - "traefik.public.frontend.passHostHeader=true"
</code>```

```<code>      labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_traefik"
      # Public segment
      - "traefik.public.protocol=http"
      - "traefik.public.port=8080"
      - "traefik.public.frontend.rule=Host:serviceB-gateway.traefik.dev.pbp"
      - "traefik.public.frontend.passHostHeader=true"
      - "traefik.public.backend.loadbalancer.method=drr"
</code>```

The first one is a grpc service I am running and the second one is an HTTP gateway for the grpc service.
The 2nd one works as expected. There is nothing weird there except the fact that the certificate is insecure.
However, I find it really hard to make the grpc service exposed by Traefik.
If I execute grpcurl -plaintext tag-service-grpc.traefik.dev.pbp:443 list I get the result Failed to list services: rpc error: code = Unknown desc = Internal Server Error
and the Traefic logs are

```<code>{"BackendAddr":"","BackendName":"Traefik","BackendURL":{"Scheme":"","Opaque":"","User":null,"Host":"","Path":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RawPath":"","ForceQuery":false,"RawQuery":"","Fragment":""},"ClientAddr":"x.x.x.x:64391","ClientHost":"x.x.x.x","ClientPort":"64391","ClientUsername":"-","DownstreamContentSize":0,"DownstreamStatus":500,"DownstreamStatusLine":"500 Internal Server Error","Duration":426232,"FrontendName":"Auth for frontend-public-tag-service-public","OriginContentSize":0,"OriginDuration":222656,"OriginStatus":500,"OriginStatusLine":"500 Internal Server Error","Overhead":203576,"RequestAddr":"serviceA-grpc.traefik.dev.pap:443","RequestContentSize":0,"RequestCount":14,"RequestHost":"serviceA-grpc.traefik.dev.pap","RequestLine":"POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo HTTP/2.0","RequestMethod":"POST","RequestPath":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RequestPort":"443","RequestProtocol":"HTTP/2.0","RetryAttempts":0,"StartLocal":"2019-05-24T20:24:24.216358162Z","StartUTC":"2019-05-24T20:24:24.216358162Z","level":"info","msg":"","request_Content-Type":"application/grpc","request_Te":"trailers","request_User-Agent":"grpc-go/1.19.0","time":"2019-05-24T20:24:24Z"}
{"BackendAddr":"","BackendName":"Traefik","BackendURL":{"Scheme":"","Opaque":"","User":null,"Host":"","Path":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RawPath":"","ForceQuery":false,"RawQuery":"","Fragment":""},"ClientAddr":"x.x.x.x:64391","ClientHost":"x.x.x.x","ClientPort":"64391","ClientUsername":"-","DownstreamContentSize":0,"DownstreamStatus":500,"DownstreamStatusLine":"500 Internal Server Error","Duration":398352,"FrontendName":"Auth for frontend-public-tag-service-public","OriginContentSize":0,"OriginDuration":142857,"OriginStatus":500,"OriginStatusLine":"500 Internal Server Error","Overhead":255495,"RequestAddr":"serviceA-grpc.traefik.dev.pap:443","RequestContentSize":0,"RequestCount":15,"RequestHost":"serviceA-grpc.traefik.dev.pap","RequestLine":"POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo HTTP/2.0","RequestMethod":"POST","RequestPath":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RequestPort":"443","RequestProtocol":"HTTP/2.0","RetryAttempts":0,"StartLocal":"2019-05-24T20:24:24.297632103Z","StartUTC":"2019-05-24T20:24:24.297632103Z","level":"info","msg":"","request_Content-Type":"application/grpc","request_Te":"trailers","request_User-Agent":"grpc-go/1.19.0","time":"2019-05-24T20:24:24Z"}
</code>```

If I execute grpcurl -plaintext docker-swarm-worker-01.dev.pap:50061 list I get the list of services I can call.
Can someone help me please?

答:
I managed to make it work! It seems that the problem was the redirecting of http to https and the basic http authentication that I was using.

Traefik.toml config file now is simpler:

```<code>defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.http]
    address = ":80"
    compress = true
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/certs/certfile.cert"
      keyFile = "/certs/keyfile.key"

  [entryPoints.api]
    address = ":8081"
  [entryPoints.ping]
    address = ":8082"

[api]
  entryPoint = "api"
  dashboard = true

[ping]
  entryPoint = "ping"

[retry]

[traefikLog]
  format   = "json"

[accessLog]
  format = "json"

[docker]
  endpoint = "unix:///var/run/docker.sock"
  domain = "traefik.dev.pbp"
  swarmmode = true
  watch = true
  exposedByDefault = false
  insecureSkipVerify = true
</code>```

Now I can connect to my grpc service running on Docker swarm through Traefik!

ContentLicense: CC BY-SA 4.0

Body:
I have been trying to configure Traefik to be the reverse proxy for my dev docker swarm which runs on its own VPN, isolated from the outer world.
The swarm consists of 3 manager nodes and 3 worker nodes and it does not have any TLS for communication between them.
I have managed to properly set a number of frontends (with rules for Host) and backends that point to services running in the swarm.
Below, is my docker-compose file which I use to deploy the docker stack for traefik on the swarm.

version: '3.6'

networks:
  traefik:
    driver: overlay

configs:
  traefik:
    file: ./config.dev.toml

services:
  traefik:
    image: traefik:1.7
    command:
      - --docker
      - --docker.swarmMode
      - --docker.domain=traefik.dev.pap
      - --docker.exposedByDefault=false
      - --entryPoints=Name:http Address::80 Redirect.EntryPoint:https
      - --entryPoints=Name:https Address::443 TLS:/certs/certfile.cert,/certs/keyfile.key
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    configs:
      - source: traefik
        target: /traefik.toml
    networks:
      - traefik
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
      - target: 8080
        published: 8080
        mode: host
      - target: 8081
        published: 8081
        mode: host
      - target: 8082
        published: 8082
        mode: host
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure

Toml file for traefik

defaultEntryPoints = ["http", "https"]

logLevel = "WARN"

insecureSkipVerify = true

[entryPoints]
  [entryPoints.http]
    address = ":80"
    [entryPoints.http.auth.basic]
    users = ["traefik:$2y$05$ZF08gDSv0f88vEUVzmwuxu.9seYIAZVzTMXnrETBDhQT30dxu4vOu"]
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = """-----BEGIN CERTIFICATE-----
                    MIICsjCCAZoCCQDP9WReX5fgQjANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBAq
                    dHJhZWZpay5kZXYucGFwMB4XDTE5MDUyNDIwMTYzMloXDTIwMDUyMzIwMTYzMlow
                    GzEZMBcGA1UEAwwQKnRyYWVmaWsuZGV2LnBhcDCCASIwDQYJKoZIhvcNAQEBBQAD
                    ggEPADCCAQoCggEBAJ86nJMpyENKQrsDlfrMI8TwdAuHXXLpglMSPVmmTzm0Y7F7
                    CVRAwl8NJdbBJnBmK3+vaG1P3WfXfu/pBfn8GDrvlJd+1XqKdExMYMCDy2Ay1ghk
                    1mOcRkJ2XS2h7FjvGjAmE7/icYZprRziek/4hLCtpTjPwPIx/5tN/ZR+lpMXe+dG
                    24CqvcTftZCS+RZSMuACG0tKlmhOx/xjoUOQMiEA8ysmQE+RrEs7ZSvu1SLYMILa
                    jGrHmH/52kIia+zOJqi8k4pVTkRFB1CNeSURgFOQf1zWzSI49GTh0UGsmlgeMoOX
                    FgrEjsbmMKxCz8ItPiTMjJ1zLd5YyBt+ATeDl0kCAwEAATANBgkqhkiG9w0BAQsF
                    AAOCAQEAYXrBbyJ75TMInYmPjkPD/Vdh3dI62qwHrKJsXN519FC8gbYSJFSdr5Pd
                    y/stM2Xn8KGgnkLSuo62MzGD15X/IYqn4Kt9Eizqd5kpsdNc7l/pTTidcCY3nQ82
                    CUGQrnwyVjZ/8wwbjtTL1TOismK3yA169WXD2yXGz15fR08lLCMqXEKotl82FxfX
                    6mw9EkLC3MAfIxuuWcaCl8/AHAUlrzrQOoVj9OkBcxwYeYH++KKYOGCaiuKMen9x
                    cjyCo05qmBQq4PWOoafDJMrdAcnzjc0tTW3DBTnJY7tR0qA/6iGVsdlHce6rMZtR
                    sb5m6XFgABCcg54yfrHIGgv1Te78aA==
                    -----END CERTIFICATE-----
                    """
      keyFile = """-----BEGIN PRIVATE KEY-----
                    MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCfOpyTKchDSkK7
                    A5X6zCPE8HQLh11y6YJTEj1Zpk85tGOxewlUQMJfDSXWwSZwZit/r2htT91n137v
                    6QX5/Bg675SXftV6inRMTGDAg8tgMtYIZNZjnEZCdl0toexY7xowJhO/4nGGaa0c
                    4npP+ISwraU4z8DyMf+bTf2UfpaTF3vnRtuAqr3E37WQkvkWUjLgAhtLSpZoTsf8
                    Y6FDkDIhAPMrJkBPkaxLO2Ur7tUi2DCC2oxqx5h/+dpCImvsziaovJOKVU5ERQdQ
                    jXklEYBTkH9c1s0iOPRk4dFBrJpYHjKDlxYKxI7G5jCsQs/CLT4kzIydcy3eWMgb
                    fgE3g5dJAgMBAAECggEBAJb3QyxkGPNznQEizTgUBHXcZKnplbg1nNKWIIS3IbZc
                    SYkkVhwDqkXkeVO7nW5D8EoHTMMXTZv+vONJ09jII1D9hax9HHoqe0k7wR/F1TVH
                    /ZXHxVx79kFdZ8q0Exne2L193Iu5blk6KF+SetUHkwbQHC5ZC16V+PqOXzZDLxAV
                    XOXjv5nOK2bqffgZdjYmW3fiwARJ1y/2s6G2Pn3Uk9z3Hk259ZI6k1zE4mwmf62t
                    FQJfjDQ7Ej7N0lXwmSA/Kb7qTXQ/div+juGlEjKTZIZRJMcLOxaZMo93sU8T/Y6b
                    wWnsRvEZlZ9yy8Y/OWN3UxWjc6nx8DPI6sYnTBUNEmECgYEA0Co6Px6n4CFtmeT6
                    6vj/YNGY1vzrycqixtymaIJk7TmPXeLqL919Sro/jbI0B189tnm3DFLk458feRaA
                    Nw+Jl1vQo9IjutJ1ujNt7IrCtlP6smRpQ5fXQ9Ywk3IPtZiG9W+fxM1uHSYKoAh/
                    sAym38Ao5hPRoRJ0TJxvlkCJtz8CgYEAw9GdFa+CXcx9U8pZE1tV2J9gXjd0mr10
                    OKjpKA9ez8IOB9S96bNOiEwHzzsza+OFoou1DrIK0zoK2+XYZYJ+sWOU1pO4PYlj
                    vbRC5kFb2EvD5h47oIoAWqk3QOGewM+z6eWI9r4LTOgdiZ1r6c73jydGGtTBtcZq
                    oqgVOziHV3cCgYEAgtw495se77A0BU3ES1iyujuo+GXRGG7xe1AUsJhgOB06Okw+
                    6k4zyHljIIGJYaUG16KWZwHpcAqFL4rsmTCET4lhlMqyuWw6pA5WqR/mHdaXP/QN
                    lHds1PFeYiKPK5qyJLLCXmbCNULH5SjSlGqvsPNNAq4s1zQRtmOVZoA10uMCgYBw
                    laPrQ+2AYIHuGvj72BeTZI7TnK6+CQ85RGRJVAz/BmNqvTYzl5QfaRdUXoVCEp5S
                    xmBjApqWt1hm9c9lDZIqC0cX1/al6sgd2fZczFcyFN2dAOTneHCbr47FDvNniAO5
                    Bu+obbuxjALvjELvOr+63qm/43M8P8gvnNQYKHgoIQKBgQCQJrT3z27O/hRVUIGg
                    bwAmzwGExOC39uLHNWmOcVmw36oV592sVw1K9pRvPFVJp956T63lhcGv4t0ki2DE
                    gBN/V1jhkAw33qRDd5bbYmIutf6RO7HeewwFHpbaLw0FULe5UlsziE9AbTHmddqU
                    GTcyajXnqimXvSu6AC9XFA9s4g==
                    -----END PRIVATE KEY-----
                   """
  [entryPoints.api]
    address = ":8081"
  [entryPoints.ping]
    address = ":8082"

[api]
  entryPoint = "api"
  dashboard = true

[ping]
  entryPoint = "ping"

[retry]
  logLevel = "DEBUG"

[traefikLog]
  logLevel = "DEBUG"
  format   = "json"

[accessLog]
  logLevel = "DEBUG"
  format = "json"

[docker]
  endpoint = "unix:///var/run/docker.sock"
  domain = "traefik.dev.pbp"
  swarmmode = true
  watch = true
  exposedByDefault = false

The certificates above were generated on my laptop with the command:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./backend.key -out ./backend.cert and Common Name:*traefik.dev.pap.

The 2 services I want to expose have the following labels:

      labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_traefik"
      # Public segment
      - "traefik.public.protocol=h2c"
      - "traefik.public.port=50051"
      - "traefik.public.frontend.rule=Host:serviceA-grpc.traefik.dev.pbp"
      - "traefik.public.frontend.auth.forward.tls.insecureSkipVerify=true"
      - "traefik.public.backend.loadbalancer.method=drr"
      - "traefik.public.frontend.passHostHeader=true"

      labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_traefik"
      # Public segment
      - "traefik.public.protocol=http"
      - "traefik.public.port=8080"
      - "traefik.public.frontend.rule=Host:serviceB-gateway.traefik.dev.pbp"
      - "traefik.public.frontend.passHostHeader=true"
      - "traefik.public.backend.loadbalancer.method=drr"

The first one is a grpc service I am running and the second one is an HTTP gateway for the grpc service.
The 2nd one works as expected. There is nothing weird there except the fact that the certificate is insecure.
However, I find it really hard to make the grpc service exposed by Traefik.
If I execute grpcurl -plaintext tag-service-grpc.traefik.dev.pbp:443 list I get the result Failed to list services: rpc error: code = Unknown desc = Internal Server Error
and the Traefic logs are

{"BackendAddr":"","BackendName":"Traefik","BackendURL":{"Scheme":"","Opaque":"","User":null,"Host":"","Path":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RawPath":"","ForceQuery":false,"RawQuery":"","Fragment":""},"ClientAddr":"x.x.x.x:64391","ClientHost":"x.x.x.x","ClientPort":"64391","ClientUsername":"-","DownstreamContentSize":0,"DownstreamStatus":500,"DownstreamStatusLine":"500 Internal Server Error","Duration":426232,"FrontendName":"Auth for frontend-public-tag-service-public","OriginContentSize":0,"OriginDuration":222656,"OriginStatus":500,"OriginStatusLine":"500 Internal Server Error","Overhead":203576,"RequestAddr":"serviceA-grpc.traefik.dev.pap:443","RequestContentSize":0,"RequestCount":14,"RequestHost":"serviceA-grpc.traefik.dev.pap","RequestLine":"POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo HTTP/2.0","RequestMethod":"POST","RequestPath":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RequestPort":"443","RequestProtocol":"HTTP/2.0","RetryAttempts":0,"StartLocal":"2019-05-24T20:24:24.216358162Z","StartUTC":"2019-05-24T20:24:24.216358162Z","level":"info","msg":"","request_Content-Type":"application/grpc","request_Te":"trailers","request_User-Agent":"grpc-go/1.19.0","time":"2019-05-24T20:24:24Z"}
{"BackendAddr":"","BackendName":"Traefik","BackendURL":{"Scheme":"","Opaque":"","User":null,"Host":"","Path":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RawPath":"","ForceQuery":false,"RawQuery":"","Fragment":""},"ClientAddr":"x.x.x.x:64391","ClientHost":"x.x.x.x","ClientPort":"64391","ClientUsername":"-","DownstreamContentSize":0,"DownstreamStatus":500,"DownstreamStatusLine":"500 Internal Server Error","Duration":398352,"FrontendName":"Auth for frontend-public-tag-service-public","OriginContentSize":0,"OriginDuration":142857,"OriginStatus":500,"OriginStatusLine":"500 Internal Server Error","Overhead":255495,"RequestAddr":"serviceA-grpc.traefik.dev.pap:443","RequestContentSize":0,"RequestCount":15,"RequestHost":"serviceA-grpc.traefik.dev.pap","RequestLine":"POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo HTTP/2.0","RequestMethod":"POST","RequestPath":"/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo","RequestPort":"443","RequestProtocol":"HTTP/2.0","RetryAttempts":0,"StartLocal":"2019-05-24T20:24:24.297632103Z","StartUTC":"2019-05-24T20:24:24.297632103Z","level":"info","msg":"","request_Content-Type":"application/grpc","request_Te":"trailers","request_User-Agent":"grpc-go/1.19.0","time":"2019-05-24T20:24:24Z"}

If I execute grpcurl -plaintext docker-swarm-worker-01.dev.pap:50061 list I get the list of services I can call.
Can someone help me please?

Body:
I managed to make it work! It seems that the problem was the redirecting of http to https and the basic http authentication that I was using.

Traefik.toml config file now is simpler:

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.http]
    address = ":80"
    compress = true
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/certs/certfile.cert"
      keyFile = "/certs/keyfile.key"

  [entryPoints.api]
    address = ":8081"
  [entryPoints.ping]
    address = ":8082"

[api]
  entryPoint = "api"
  dashboard = true

[ping]
  entryPoint = "ping"

[retry]

[traefikLog]
  format   = "json"

[accessLog]
  format = "json"

[docker]
  endpoint = "unix:///var/run/docker.sock"
  domain = "traefik.dev.pbp"
  swarmmode = true
  watch = true
  exposedByDefault = false
  insecureSkipVerify = true

Now I can connect to my grpc service running on Docker swarm through Traefik!


问:
How can I duplicate an entire entry in an XML file with VIM?
I have the following in an XML file:

```<code><TypeDef name="a">
  <ArrayType high="14" low="0">
    <UndefType type="node">
    </UndefType>
  </ArrayType>
</TypeDef>
</code>```

And I want to copy this entry.  Normally I'd go to the first line, enter Line-Visual mode using V, go down to the last line, yank and paste.

How can I copy the entire entry without looking for the end of the entry myself?

答:
In addition to Nathan's answer you might want to check out matchit.vim ... If you have a newer install you probably have it

http://www.vim.org/scripts/script.php?script_id=39

matchit extends vim's % (find matching bracket)  to cover xml/html tags and more. So for your solution the action would be from the beginning tag

```<code>V%y
</code>```

matchit is of course very useful for general navigating purposes.

OwnerDisplayName: Nathan Fellman

ContentLicense: CC BY-SA 2.5

Body:
I have the following in an XML file:

<TypeDef name="a">
  <ArrayType high="14" low="0">
    <UndefType type="node">
    </UndefType>
  </ArrayType>
</TypeDef>

And I want to copy this entry.  Normally I'd go to the first line, enter Line-Visual mode using V, go down to the last line, yank and paste.

How can I copy the entire entry without looking for the end of the entry myself?

Body:
In addition to Nathan's answer you might want to check out matchit.vim ... If you have a newer install you probably have it

http://www.vim.org/scripts/script.php?script_id=39

matchit extends vim's % (find matching bracket)  to cover xml/html tags and more. So for your solution the action would be from the beginning tag

V%y

matchit is of course very useful for general navigating purposes.

OwnerDisplayName: michael

LastEditorDisplayName: Nathan Fellman


问:
Calling onCreateContextMenu method in android?
How to call onCreateContextMenu method when I make click on ExpanadableListView child element (it is not long touch just touch only).

答: Setup onClickListener and call openContextMenu.

ContentLicense: CC BY-SA 3.0


问:
What command do I use to see what the ECDSA key fingerprint of my server is?
I see stuff all over Google on how to see the RSA key fingerprint, but not the ECDSA fingerprint.</p>

答:
Commands used

Display ascii-art of the public host key stored on the server (to be done on server side, the one you connect TO via ssh):

```<code>ssh-keygen -l -v -f /etc/ssh/ssh_host_ecdsa_key.pub
</code>```

-l: Show fingerprint of specified public key file.

-v: visual (ascii-art)

-f: file

Display ascii-art of remote server public host key (to be done on client side, the one you connect FROM via ssh):

```<code>ssh -o visualhostkey=yes -o FingerprintHash=md5 <host_server_to_connect>
</code>```

-o: option

visualhostkey: visual (ascii-art)

FingerprintHash: hash algo to use

What to do to check the authenticity of a host/server

First, 1. is to be done locally on the server (the one you want to connect TO via ssh ): it will give you a first ascii-art. Print it or take a picture.

Second, 2. is to be done at the first SSH connexion; it will display a second ascii-art. If the ascii-art is the same, then you can answer yes to the "do I trust?" question (i.e. Are you sure you want to continue connecting (yes/no)).

Example

Server side

```<code>$ ssh-keygen -l -v -f /etc/ssh/ssh_host_ecdsa_key.pub
256 2e:a6:b3:27:14:12:0b:79:df:9a:7f:bd:4d:b1:e0:b6   (ECDSA)
+--[ECDSA  256]---+
| .               |
|o o              |
| o + .           |
|  o o .          |
|   . +  S . .    |
|    +  . . . o   |
|   . .o ..o o    |
|    ooo....+     |
|    o= .  E..    |
+-----------------+
</code>```

Client side

```<code>$ ssh -o visualhostkey=yes -o FingerprintHash=md5 192.168.12.211
The authenticity of host '192.168.12.211 (192.168.12.211)' can't be established.
ECDSA key fingerprint is MD5:2e:a6:b3:27:14:12:0b:79:df:9a:7f:bd:4d:b1:e0:b6.
+---[ECDSA 256]---+
| .               |
|o o              |
| o + .           |
|  o o .          |
|   . +  S . .    |
|    +  . . . o   |
|   . .o ..o o    |
|    ooo....+     |
|    o= .  E..    |
+------[MD5]------+
Are you sure you want to continue connecting (yes/no)?
</code>```

Some more explanation

The first command will display the ascii-art corresponding to the fingerprint of the file you give as input. The file you give as input is the public host key of the server. When a client connect (not only for the first time), the server will sent its public host key. This public host key will be searched in ~/.ssh/known_hosts. If the public key is in the file, then it's ok: the host (server) is known, so we move on to the next step to authentificate the user (user auth is not described in this post). If the public key is not in the file, then the client will compute the fingerprint of this public host key with a hash algorithm (a different hash algo will give a different fingerprint). This fingerprint previously calculated is displayed (along with the ascii-art if corresponding option provided) and you will have to answer yes or no depending on you recognising this fingerprint or no (this fingerprint is the image/hash of the public host key of the server). If you say yes, then the bublic key of the server (not its fingerprint) will be added to the file ~/.ssh/known_hosts.

We can notice that ~/.ssh/known_hosts is under you home (~) directory, because you trust this host (server), but a different user may not trust the same as you. Also, the host public key of the server is not user-dependent, so it is stored in /etc/ssh/.

The second command will display the fingerprint and the ascii-art of the public key received from the host_server_to_connect (according to the hash algo given in options). It is the same as doing only ssh, but with more visual options, so the connection will continue the same way as a normal ssh connexion.

Body:
Commands used

Display ascii-art of the public host key stored on the server (to be done on server side, the one you connect TO via ssh):

ssh-keygen -l -v -f /etc/ssh/ssh_host_ecdsa_key.pub

-l: Show fingerprint of specified public key file.

-v: visual (ascii-art)

-f: file

Display ascii-art of remote server public host key (to be done on client side, the one you connect FROM via ssh):

ssh -o visualhostkey=yes -o FingerprintHash=md5 <host_server_to_connect>

-o: option

visualhostkey: visual (ascii-art)

FingerprintHash: hash algo to use

What to do to check the authenticity of a host/server

First, 1. is to be done locally on the server (the one you want to connect TO via ssh ): it will give you a first ascii-art. Print it or take a picture.

Second, 2. is to be done at the first SSH connexion; it will display a second ascii-art. If the ascii-art is the same, then you can answer yes to the "do I trust?" question (i.e. Are you sure you want to continue connecting (yes/no)).

Example

Server side

$ ssh-keygen -l -v -f /etc/ssh/ssh_host_ecdsa_key.pub
256 2e:a6:b3:27:14:12:0b:79:df:9a:7f:bd:4d:b1:e0:b6   (ECDSA)
+--[ECDSA  256]---+
| .               |
|o o              |
| o + .           |
|  o o .          |
|   . +  S . .    |
|    +  . . . o   |
|   . .o ..o o    |
|    ooo....+     |
|    o= .  E..    |
+-----------------+

Client side

$ ssh -o visualhostkey=yes -o FingerprintHash=md5 192.168.12.211
The authenticity of host '192.168.12.211 (192.168.12.211)' can't be established.
ECDSA key fingerprint is MD5:2e:a6:b3:27:14:12:0b:79:df:9a:7f:bd:4d:b1:e0:b6.
+---[ECDSA 256]---+
| .               |
|o o              |
| o + .           |
|  o o .          |
|   . +  S . .    |
|    +  . . . o   |
|   . .o ..o o    |
|    ooo....+     |
|    o= .  E..    |
+------[MD5]------+
Are you sure you want to continue connecting (yes/no)?

Some more explanation

The first command will display the ascii-art corresponding to the fingerprint of the file you give as input. The file you give as input is the public host key of the server. When a client connect (not only for the first time), the server will sent its public host key. This public host key will be searched in ~/.ssh/known_hosts. If the public key is in the file, then it's ok: the host (server) is known, so we move on to the next step to authentificate the user (user auth is not described in this post). If the public key is not in the file, then the client will compute the fingerprint of this public host key with a hash algorithm (a different hash algo will give a different fingerprint). This fingerprint previously calculated is displayed (along with the ascii-art if corresponding option provided) and you will have to answer yes or no depending on you recognising this fingerprint or no (this fingerprint is the image/hash of the public host key of the server). If you say yes, then the bublic key of the server (not its fingerprint) will be added to the file ~/.ssh/known_hosts.

We can notice that ~/.ssh/known_hosts is under you home (~) directory, because you trust this host (server), but a different user may not trust the same as you. Also, the host public key of the server is not user-dependent, so it is stored in /etc/ssh/.

The second command will display the fingerprint and the ascii-art of the public key received from the host_server_to_connect (according to the hash algo given in options). It is the same as doing only ssh, but with more visual options, so the connection will continue the same way as a normal ssh connexion.


问:
Angular 7 installing bootstrap
I'm following the "Pro Angular 6" book which should work with Angular 7. I start the project like so;

Install angular cli

```<code>sudo npm install -g @angular/cli
</code>```

NOTE: This installed version 7.3.0 of the cli tool

Now install the TODO app

```<code>ng new todo
cd todo
ng serve --port 3001 --open
</code>```

This works, then I add in bootstrap

```<code>npm install bootstrap@4.1.1
</code>```

And I add the following to styles

```<code>        "styles": [
          "src/styles.css",
          "node_modules/bootstrap/dist/css/bootstrap.min.css"
        ],
</code>```

Now when I serve the project I get the following error;

```<code>$ ng serve --port 3001 --open
** Angular Live Development Server is listening on localhost:3001, open your browser on http://localhost:3001/ **

Date: 2019-02-04T00:42:38.279Z
Hash: 3b3bf9a4d6733eee0b6c
Time: 5466ms
chunk {es2015-polyfills} es2015-polyfills.js, es2015-polyfills.js.map (es2015-polyfills) 5.07 kB [initial] [rendered]
chunk {main} main.js, main.js.map (main) 1.88 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 2.09 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.08 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 1.03 MB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 327 kB [initial] [rendered]

ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/array' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/date' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/function' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/map' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/math' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/number' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/object' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/parse-float' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/parse-int' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-jit-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/reflect' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/regexp' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/set' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/string' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/symbol' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/weak-map' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js
Module not found: Error: Can't resolve 'core-js/es7/reflect' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in node_modules/@angular/common/src/location/location.d.ts(8,34): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/common/src/pipes/async_pipe.d.ts(9,28): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/application_ref.d.ts(8,28): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/event_emitter.d.ts(8,39): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/linker/query_list.d.ts(8,28): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/util/lang.d.ts(8,28): error TS2307: Cannot find module 'rxjs'.
src/app/app.component.ts(3,1): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.

ℹ ｢wdm｣: Failed to compile.
</code>```

答:
You have to add --save during the installation so that angular will add this dependency inside the package.json. try below code.

npm install bootstrap@4.1.1 --save

Title: Angular 7 installing bootstrap

Body:
I'm following the "Pro Angular 6" book which should work with Angular 7. I start the project like so;

Install angular cli

sudo npm install -g @angular/cli

NOTE: This installed version 7.3.0 of the cli tool

Now install the TODO app

ng new todo
cd todo
ng serve --port 3001 --open

This works, then I add in bootstrap

npm install bootstrap@4.1.1

And I add the following to styles

        "styles": [
          "src/styles.css",
          "node_modules/bootstrap/dist/css/bootstrap.min.css"
        ],

Now when I serve the project I get the following error;

$ ng serve --port 3001 --open
** Angular Live Development Server is listening on localhost:3001, open your browser on http://localhost:3001/ **

Date: 2019-02-04T00:42:38.279Z
Hash: 3b3bf9a4d6733eee0b6c
Time: 5466ms
chunk {es2015-polyfills} es2015-polyfills.js, es2015-polyfills.js.map (es2015-polyfills) 5.07 kB [initial] [rendered]
chunk {main} main.js, main.js.map (main) 1.88 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 2.09 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.08 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 1.03 MB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 327 kB [initial] [rendered]

ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/array' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/date' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/function' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/map' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/math' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/number' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/object' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/parse-float' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/parse-int' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-jit-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/reflect' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/regexp' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/set' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/string' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/symbol' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/es2015-polyfills.js
Module not found: Error: Can't resolve 'core-js/es6/weak-map' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in ./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js
Module not found: Error: Can't resolve 'core-js/es7/reflect' in '/home/map7/code/pro_angular_6/chap2_prep/todo/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models'
ERROR in node_modules/@angular/common/src/location/location.d.ts(8,34): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/common/src/pipes/async_pipe.d.ts(9,28): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/application_ref.d.ts(8,28): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/event_emitter.d.ts(8,39): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/linker/query_list.d.ts(8,28): error TS2307: Cannot find module 'rxjs'.
node_modules/@angular/core/src/util/lang.d.ts(8,28): error TS2307: Cannot find module 'rxjs'.
src/app/app.component.ts(3,1): error TS2354: This syntax requires an imported helper but module 'tslib' cannot be found.

ℹ ｢wdm｣: Failed to compile.


问:
iOS - Linker Error, Duplicate Symbol
It seems I am having an error when attempting to compile and it seems to be pointing to two files directly..MenuViewController and FirstTopViewController. I think it has something to do with my imports, as each of them is importing the other, however the error is referencing my Building object, which is barely used in it. Also, with the clang error, how do I use -v to see the invocation?

Error:

```<code>ld: duplicate symbol _OBJC_CLASS_$_Building in /Users/alexmuller/Library/Developer/Xcode/DerivedData/ECSlidingViewController-gjxwxiwumgohyehiawnlamggzmop/Build/Intermediates/ECSlidingViewController.build/Debug-iphonesimulator/ECSlidingViewController.build/Objects-normal/i386/FirstTopViewController.o and /Users/alexmuller/Library/Developer/Xcode/DerivedData/ECSlidingViewController-gjxwxiwumgohyehiawnlamggzmop/Build/Intermediates/ECSlidingViewController.build/Debug-iphonesimulator/ECSlidingViewController.build/Objects-normal/i386/MenuViewController.o for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
</code>```

FirstTopViewController.h

```<code>#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "ECSlidingViewController.h"
#import "MenuViewController.h"
#import "TimesViewController.h"
#import "BuildingViewController.h"
#import "BuildingAnnotation.h"
#import <MapKit/MapKit.h>

@class BuildingViewController;

@interface FirstTopViewController : UIViewController <MKMapViewDelegate> {
    IBOutlet MKMapView *_map;
    BuildingViewController *buildingVC;
    BuildingAnnotation *buildAnnotation;
}

@property (nonatomic, strong) MKMapView *map;

- (IBAction)revealMenu:(id)sender;
- (IBAction)revealTimes:(id)sender;
- (void)loadBuilding:(Building *)building;

@end
</code>```

FirstTopViewController.m

```<code>#import "FirstTopViewController.h"

@implementation FirstTopViewController

@synthesize map = _map;

- (void)viewDidLoad {

    buildingVC = (BuildingViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"BuildingList"];
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [(UIView *)[self.view viewWithTag:10] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"RedWithNoise"]]];
    [super viewWillAppear:animated];
    [[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"toolbar"] forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setTitleTextAttributes:
     [NSDictionary dictionaryWithObjectsAndKeys:
      [UIColor colorWithRed:204.0/255.0 green:204.0/255.0 blue:102.0/255.0 alpha:1.0],
      UITextAttributeTextColor,
      [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8],
      UITextAttributeTextShadowColor,
      [NSValue valueWithUIOffset:UIOffsetMake(0, -1)],
      UITextAttributeTextShadowOffset,
      [UIFont fontWithName:@"AGaramondPro-Regular" size:23.0],
      UITextAttributeFont,
      nil]];
    self.view.layer.shadowOffset = CGSizeZero;
    self.view.layer.shadowOpacity = 0.75f;
    self.view.layer.shadowRadius = 10.0f;
    self.view.layer.shadowColor = [UIColor blackColor].CGColor;
    self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
    self.view.clipsToBounds = NO;

    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(30.451667, -84.268533), 16090.344, 16090.344);
    viewRegion = [_map regionThatFits:viewRegion];
    [_map setRegion:viewRegion animated:YES];

    if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]]) {
        self.slidingViewController.underLeftViewController  = [self.storyboard instantiateViewControllerWithIdentifier:@"Menu"];
    }

    if (![self.slidingViewController.underRightViewController isKindOfClass:[TimesViewController class]]) {
        self.slidingViewController.underRightViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"Times"];
    }

    [self.view addGestureRecognizer:self.slidingViewController.panGesture];

}

- (void)loadBuilding:(Building *)building {
    if (buildingVC.buildingSelected) {
        if (buildAnnotation != nil) {
            [_map removeAnnotation:buildAnnotation];
        }
        NSLog(@"%@", building.getName);
        buildAnnotation = [[BuildingAnnotation alloc] initWithCoordinate:building.getLocation.coordinate withName:building.getName withAddress:building.getAddress];
        [_map setCenterCoordinate:buildAnnotation.coordinate animated:YES];
        [_map addAnnotation:buildAnnotation];
    }
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  self.view.layer.shadowPath = nil;
  self.view.layer.shouldRasterize = YES;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
  self.view.layer.shouldRasterize = NO;
}

- (IBAction)revealMenu:(id)sender
{
  [self.slidingViewController anchorTopViewTo:ECRight];
}

- (IBAction)revealTimes:(id)sender {
    [self.slidingViewController anchorTopViewTo:ECLeft];
}

@end
</code>```

MenuViewController.h

```<code>#import <UIKit/UIKit.h>
#import "ECSlidingViewController.h"
#import "FirstTopViewController.h"
#import "TimesViewController.h"

@interface MenuViewController : UIViewController <UITableViewDataSource, UITabBarControllerDelegate> {
    NSIndexPath *selectedIndex;
}

@end
</code>```

MenuViewController.m

```<code>#import "MenuViewController.h"

typedef enum {
    ENGINEERING,
    GARNET,
    GOLD,
    HERITAGE,
    NIGHT,
    OSCEOLA,
    RENEGADE,
    TOMAHAWK
} RouteName;

@interface MenuViewController()
@property (nonatomic, strong) NSArray *menuItems;
@property (nonatomic, strong) NSArray *optionItems;
@property (nonatomic, strong) NSArray *arrayItems;

- (UIImage *)determineActiveRoute:(RouteName)route;
@end

@implementation MenuViewController
@synthesize menuItems, optionItems, arrayItems;

- (void)awakeFromNib
{

    self.menuItems = [NSArray arrayWithObjects:@"Engineering", @"Garnet", @"Gold", @"Heritage Grove", @"Night Nole", @"Osceola", @"Renegade", @"Tomahawk", nil];
    self.optionItems = [NSArray arrayWithObjects:@"Buildings", @"Directions", nil];
    self.arrayItems = [NSArray arrayWithObjects:self.menuItems, self.optionItems, nil];
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  [self.slidingViewController setAnchorRightRevealAmount:200.0f];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex
{
  return [[self.arrayItems objectAtIndex:sectionIndex] count];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.arrayItems count];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 35;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *sectionView = [[UIView alloc] init];
    [sectionView sizeToFit];
    sectionView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navCellDivider"]];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 100, 20)];
    label.textColor = [UIColor grayColor];
    label.backgroundColor = [UIColor clearColor];
    label.font = [UIFont fontWithName:@"AGaramondPro-Regular" size:12.0];
    if(section == 0)
        label.text = @"BUS ROUTES";
    else
        label.text = @"OTHER OPTIONS";
    [sectionView addSubview:label];
    return sectionView;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UILabel *label;
    UIImageView *imageView;
    NSString *cellIdentifier = @"MenuItemCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    }
    UIView *selectedView = [[UIView alloc] initWithFrame:cell.frame];
    selectedView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navCellBackgroundSelected"]];
    cell.selectedBackgroundView = selectedView;
    cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navCellBackground"]];
    label = (UILabel *)[cell.contentView viewWithTag:100];
    label.font = [UIFont fontWithName:@"AGaramondPro-Regular" size:15.0];
    label.text = [[self.arrayItems objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    imageView = (UIImageView *)[cell.contentView viewWithTag:101];
    if (indexPath.section == 0) {
        [imageView setImage:[self determineActiveRoute:indexPath.row]];
    } else {
        if (indexPath.row == 0) {
            [imageView setImage:[UIImage imageNamed:@"building"]];
        } else {
            [imageView setImage:[UIImage imageNamed:@"60-signpost"]];
        }
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    /* Type cast view as a First Top to make it easier to read. Do switch to select correct route,
        then modify map afterwards to load up correct route.
     TimesViewController can be set to the corresponding times when selected
     */
    FirstTopViewController *mapViewController = (FirstTopViewController *)self.slidingViewController.topViewController;
    TimesViewController *timesViewController = (TimesViewController *)self.slidingViewController.underRightViewController;

    if (indexPath.section == 0) {
        selectedIndex = indexPath;
        switch (indexPath.row) {
            case ENGINEERING:
                NSLog(@"Engineering Selected\n");
                timesViewController.times.text = @"Engineering";
                break;
            case GARNET:
                NSLog(@"Garnet Selected\n");
                timesViewController.times.text = @"Garnet";
                break;
            case GOLD:
                NSLog(@"Gold Selected\n");
                timesViewController.times.text = @"Gold";
                break;
            case HERITAGE:
                NSLog(@"Heritage Grove Selected\n");
                timesViewController.times.text = @"Heritage Grove";
                break;
            case NIGHT:
                NSLog(@"Night Nole Selected\n");
                timesViewController.times.text = @"Night Nole";
                break;
            case OSCEOLA:
                NSLog(@"Osceola Selected\n");
                timesViewController.times.text = @"Osceola";
                break;
            case RENEGADE:
                NSLog(@"Renegade Selected\n");
                timesViewController.times.text = @"Renegade";
                break;
            case TOMAHAWK:
                NSLog(@"Tomahawk Selected\n");
                timesViewController.times.text = @"Tomahawk";
                break;
            default:
                break;
        }
    } else {
        if (indexPath.row == 0) {
            BuildingViewController *buildings = [self.storyboard instantiateViewControllerWithIdentifier:@"BuildingList"];
            buildings.userLoc = [[CLLocation alloc] initWithLatitude:mapViewController.map.userLocation.coordinate.latitude longitude:mapViewController.map.userLocation.coordinate.longitude];

            [self presentModalViewController:buildings animated:YES];
        }
        [tableView deselectRowAtIndexPath:indexPath animated:NO];
        [tableView selectRowAtIndexPath:selectedIndex animated:YES scrollPosition:UITableViewScrollPositionNone];
    }
    [self.slidingViewController anchorTopViewTo:ECRight animations:nil onComplete:^{
        [self.slidingViewController resetTopView];
    }];
}

- (UIImage *)determineActiveRoute:(RouteName)route {
    NSCalendar *gregorianCalender = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [gregorianCalender components:NSHourCalendarUnit fromDate:[NSDate date]];
    switch (route) {
        case ENGINEERING:
            if ([components day] % 7 == 2) {
                if (([components hour] >= 7) && ([components hour] < 17)) {
                    return [UIImage imageNamed:@"green"];
                } else {
                    return [UIImage imageNamed:@"red"];
                }
            } else if (([components day] % 7 == 3) || ([components day] % 7 == 4)) {
                return [UIImage imageNamed:@"red"];
            } else {
                //Weekday
                if (([components hour] >= 7) && ([components hour] < 19)) {
                    return [UIImage imageNamed:@"green"];
                } else {
                    return [UIImage imageNamed:@"red"];
                }
            }
            break;
        case GARNET:
        case GOLD:
        case HERITAGE:
            if ((([components day] % 7 <= 3) || ([components day] % 7 >= 5)) &&
                (([components hour] >= 7) && ([components hour] <= 19))) {
                return [UIImage imageNamed:@"green"];
            } else {
                return [UIImage imageNamed:@"red"];
            }
            break;
        case NIGHT:
            if ((([components day] % 7 == 6) || ([components day] % 7 <= 3)) &&
                (([components hour] >= 22.5) || ([components hour] <= 3))) {
                return [UIImage imageNamed:@"green"];
            } else {
                return [UIImage imageNamed:@"red"];
            }
            break;
        case OSCEOLA:
        case RENEGADE:
        case TOMAHAWK:
            if ((([components day] % 7 <= 3) || ([components day] % 7 >= 5)) &&
                (([components hour] >= 7) && ([components hour] <= 19))) {
                return [UIImage imageNamed:@"green"];
            } else {
                return [UIImage imageNamed:@"red"];
            }
            break;
    }
}

@end
</code>```

答: I encountered this problem, because both ICMGameDemo and CMGameSDK added that .m file into the compile sources panel, I drop the ICMGameDemo's and re-build the problem gone.

Title: iOS - Linker Error, Duplicate Symbol

Body:
It seems I am having an error when attempting to compile and it seems to be pointing to two files directly..MenuViewController and FirstTopViewController. I think it has something to do with my imports, as each of them is importing the other, however the error is referencing my Building object, which is barely used in it. Also, with the clang error, how do I use -v to see the invocation?

Error:

ld: duplicate symbol _OBJC_CLASS_$_Building in /Users/alexmuller/Library/Developer/Xcode/DerivedData/ECSlidingViewController-gjxwxiwumgohyehiawnlamggzmop/Build/Intermediates/ECSlidingViewController.build/Debug-iphonesimulator/ECSlidingViewController.build/Objects-normal/i386/FirstTopViewController.o and /Users/alexmuller/Library/Developer/Xcode/DerivedData/ECSlidingViewController-gjxwxiwumgohyehiawnlamggzmop/Build/Intermediates/ECSlidingViewController.build/Debug-iphonesimulator/ECSlidingViewController.build/Objects-normal/i386/MenuViewController.o for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

FirstTopViewController.h

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "ECSlidingViewController.h"
#import "MenuViewController.h"
#import "TimesViewController.h"
#import "BuildingViewController.h"
#import "BuildingAnnotation.h"
#import <MapKit/MapKit.h>

@class BuildingViewController;

@interface FirstTopViewController : UIViewController <MKMapViewDelegate> {
    IBOutlet MKMapView *_map;
    BuildingViewController *buildingVC;
    BuildingAnnotation *buildAnnotation;
}

@property (nonatomic, strong) MKMapView *map;

- (IBAction)revealMenu:(id)sender;
- (IBAction)revealTimes:(id)sender;
- (void)loadBuilding:(Building *)building;

@end

FirstTopViewController.m

#import "FirstTopViewController.h"

@implementation FirstTopViewController

@synthesize map = _map;

- (void)viewDidLoad {

    buildingVC = (BuildingViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"BuildingList"];
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [(UIView *)[self.view viewWithTag:10] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"RedWithNoise"]]];
    [super viewWillAppear:animated];
    [[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"toolbar"] forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setTitleTextAttributes:
     [NSDictionary dictionaryWithObjectsAndKeys:
      [UIColor colorWithRed:204.0/255.0 green:204.0/255.0 blue:102.0/255.0 alpha:1.0],
      UITextAttributeTextColor,
      [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8],
      UITextAttributeTextShadowColor,
      [NSValue valueWithUIOffset:UIOffsetMake(0, -1)],
      UITextAttributeTextShadowOffset,
      [UIFont fontWithName:@"AGaramondPro-Regular" size:23.0],
      UITextAttributeFont,
      nil]];
    self.view.layer.shadowOffset = CGSizeZero;
    self.view.layer.shadowOpacity = 0.75f;
    self.view.layer.shadowRadius = 10.0f;
    self.view.layer.shadowColor = [UIColor blackColor].CGColor;
    self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
    self.view.clipsToBounds = NO;

    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(30.451667, -84.268533), 16090.344, 16090.344);
    viewRegion = [_map regionThatFits:viewRegion];
    [_map setRegion:viewRegion animated:YES];

    if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]]) {
        self.slidingViewController.underLeftViewController  = [self.storyboard instantiateViewControllerWithIdentifier:@"Menu"];
    }

    if (![self.slidingViewController.underRightViewController isKindOfClass:[TimesViewController class]]) {
        self.slidingViewController.underRightViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"Times"];
    }

    [self.view addGestureRecognizer:self.slidingViewController.panGesture];

}

- (void)loadBuilding:(Building *)building {
    if (buildingVC.buildingSelected) {
        if (buildAnnotation != nil) {
            [_map removeAnnotation:buildAnnotation];
        }
        NSLog(@"%@", building.getName);
        buildAnnotation = [[BuildingAnnotation alloc] initWithCoordinate:building.getLocation.coordinate withName:building.getName withAddress:building.getAddress];
        [_map setCenterCoordinate:buildAnnotation.coordinate animated:YES];
        [_map addAnnotation:buildAnnotation];
    }
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
  self.view.layer.shadowPath = nil;
  self.view.layer.shouldRasterize = YES;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.layer.bounds].CGPath;
  self.view.layer.shouldRasterize = NO;
}

- (IBAction)revealMenu:(id)sender
{
  [self.slidingViewController anchorTopViewTo:ECRight];
}

- (IBAction)revealTimes:(id)sender {
    [self.slidingViewController anchorTopViewTo:ECLeft];
}

@end

MenuViewController.h

#import <UIKit/UIKit.h>
#import "ECSlidingViewController.h"
#import "FirstTopViewController.h"
#import "TimesViewController.h"

@interface MenuViewController : UIViewController <UITableViewDataSource, UITabBarControllerDelegate> {
    NSIndexPath *selectedIndex;
}

@end

MenuViewController.m

#import "MenuViewController.h"

typedef enum {
    ENGINEERING,
    GARNET,
    GOLD,
    HERITAGE,
    NIGHT,
    OSCEOLA,
    RENEGADE,
    TOMAHAWK
} RouteName;

@interface MenuViewController()
@property (nonatomic, strong) NSArray *menuItems;
@property (nonatomic, strong) NSArray *optionItems;
@property (nonatomic, strong) NSArray *arrayItems;

- (UIImage *)determineActiveRoute:(RouteName)route;
@end

@implementation MenuViewController
@synthesize menuItems, optionItems, arrayItems;

- (void)awakeFromNib
{

    self.menuItems = [NSArray arrayWithObjects:@"Engineering", @"Garnet", @"Gold", @"Heritage Grove", @"Night Nole", @"Osceola", @"Renegade", @"Tomahawk", nil];
    self.optionItems = [NSArray arrayWithObjects:@"Buildings", @"Directions", nil];
    self.arrayItems = [NSArray arrayWithObjects:self.menuItems, self.optionItems, nil];
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  [self.slidingViewController setAnchorRightRevealAmount:200.0f];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex
{
  return [[self.arrayItems objectAtIndex:sectionIndex] count];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.arrayItems count];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 35;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *sectionView = [[UIView alloc] init];
    [sectionView sizeToFit];
    sectionView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navCellDivider"]];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 100, 20)];
    label.textColor = [UIColor grayColor];
    label.backgroundColor = [UIColor clearColor];
    label.font = [UIFont fontWithName:@"AGaramondPro-Regular" size:12.0];
    if(section == 0)
        label.text = @"BUS ROUTES";
    else
        label.text = @"OTHER OPTIONS";
    [sectionView addSubview:label];
    return sectionView;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UILabel *label;
    UIImageView *imageView;
    NSString *cellIdentifier = @"MenuItemCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    }
    UIView *selectedView = [[UIView alloc] initWithFrame:cell.frame];
    selectedView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navCellBackgroundSelected"]];
    cell.selectedBackgroundView = selectedView;
    cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"navCellBackground"]];
    label = (UILabel *)[cell.contentView viewWithTag:100];
    label.font = [UIFont fontWithName:@"AGaramondPro-Regular" size:15.0];
    label.text = [[self.arrayItems objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    imageView = (UIImageView *)[cell.contentView viewWithTag:101];
    if (indexPath.section == 0) {
        [imageView setImage:[self determineActiveRoute:indexPath.row]];
    } else {
        if (indexPath.row == 0) {
            [imageView setImage:[UIImage imageNamed:@"building"]];
        } else {
            [imageView setImage:[UIImage imageNamed:@"60-signpost"]];
        }
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    /* Type cast view as a First Top to make it easier to read. Do switch to select correct route,
        then modify map afterwards to load up correct route.
     TimesViewController can be set to the corresponding times when selected
     */
    FirstTopViewController *mapViewController = (FirstTopViewController *)self.slidingViewController.topViewController;
    TimesViewController *timesViewController = (TimesViewController *)self.slidingViewController.underRightViewController;

    if (indexPath.section == 0) {
        selectedIndex = indexPath;
        switch (indexPath.row) {
            case ENGINEERING:
                NSLog(@"Engineering Selected\n");
                timesViewController.times.text = @"Engineering";
                break;
            case GARNET:
                NSLog(@"Garnet Selected\n");
                timesViewController.times.text = @"Garnet";
                break;
            case GOLD:
                NSLog(@"Gold Selected\n");
                timesViewController.times.text = @"Gold";
                break;
            case HERITAGE:
                NSLog(@"Heritage Grove Selected\n");
                timesViewController.times.text = @"Heritage Grove";
                break;
            case NIGHT:
                NSLog(@"Night Nole Selected\n");
                timesViewController.times.text = @"Night Nole";
                break;
            case OSCEOLA:
                NSLog(@"Osceola Selected\n");
                timesViewController.times.text = @"Osceola";
                break;
            case RENEGADE:
                NSLog(@"Renegade Selected\n");
                timesViewController.times.text = @"Renegade";
                break;
            case TOMAHAWK:
                NSLog(@"Tomahawk Selected\n");
                timesViewController.times.text = @"Tomahawk";
                break;
            default:
                break;
        }
    } else {
        if (indexPath.row == 0) {
            BuildingViewController *buildings = [self.storyboard instantiateViewControllerWithIdentifier:@"BuildingList"];
            buildings.userLoc = [[CLLocation alloc] initWithLatitude:mapViewController.map.userLocation.coordinate.latitude longitude:mapViewController.map.userLocation.coordinate.longitude];

            [self presentModalViewController:buildings animated:YES];
        }
        [tableView deselectRowAtIndexPath:indexPath animated:NO];
        [tableView selectRowAtIndexPath:selectedIndex animated:YES scrollPosition:UITableViewScrollPositionNone];
    }
    [self.slidingViewController anchorTopViewTo:ECRight animations:nil onComplete:^{
        [self.slidingViewController resetTopView];
    }];
}

- (UIImage *)determineActiveRoute:(RouteName)route {
    NSCalendar *gregorianCalender = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [gregorianCalender components:NSHourCalendarUnit fromDate:[NSDate date]];
    switch (route) {
        case ENGINEERING:
            if ([components day] % 7 == 2) {
                if (([components hour] >= 7) && ([components hour] < 17)) {
                    return [UIImage imageNamed:@"green"];
                } else {
                    return [UIImage imageNamed:@"red"];
                }
            } else if (([components day] % 7 == 3) || ([components day] % 7 == 4)) {
                return [UIImage imageNamed:@"red"];
            } else {
                //Weekday
                if (([components hour] >= 7) && ([components hour] < 19)) {
                    return [UIImage imageNamed:@"green"];
                } else {
                    return [UIImage imageNamed:@"red"];
                }
            }
            break;
        case GARNET:
        case GOLD:
        case HERITAGE:
            if ((([components day] % 7 <= 3) || ([components day] % 7 >= 5)) &&
                (([components hour] >= 7) && ([components hour] <= 19))) {
                return [UIImage imageNamed:@"green"];
            } else {
                return [UIImage imageNamed:@"red"];
            }
            break;
        case NIGHT:
            if ((([components day] % 7 == 6) || ([components day] % 7 <= 3)) &&
                (([components hour] >= 22.5) || ([components hour] <= 3))) {
                return [UIImage imageNamed:@"green"];
            } else {
                return [UIImage imageNamed:@"red"];
            }
            break;
        case OSCEOLA:
        case RENEGADE:
        case TOMAHAWK:
            if ((([components day] % 7 <= 3) || ([components day] % 7 >= 5)) &&
                (([components hour] >= 7) && ([components hour] <= 19))) {
                return [UIImage imageNamed:@"green"];
            } else {
                return [UIImage imageNamed:@"red"];
            }
            break;
    }
}

@end


问:
How do I return a count of linked objects in a GenericRelation field in a DRF Serializer?
There are a number of questions about serializing GenericRelations in Django Rest Framework however I have a use case where I want to simply return the count of objects in the GenericRelation field only and not serialize them. The documentation and existing questions I can find do not cover this.

I thought it might be as simple as returning the len(value) in a custom Serializer, however that produces the following throw:

```<code>object of type 'GenericRelatedObjectManager' has no len()
</code>```

My failed attempt:

```<code>class ObjectCountSerializer(serializers.RelatedField):
    """
    Return the count of related objects.
    """

    def to_representation(self, value):
        return len(value)

class PostListSerializer(serializers.ModelSerializer):
    """
    Main serializers for the writings module
    """
    author = MemberListSerializer(many=False, read_only=True)
    comments = ObjectCountSerializer(read_only=True)

    class Meta:
        model = Post
        fields = (
            'id',
            'slug',
            'url',
            'title',
            'description',
            'created',
            'edited',
            'author',
            'comments'
        )
        lookup_field = 'slug'
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }
</code>```

How do I simply return the count of objects in the relation?

答:
I would say a SerializerMethodField would solve this, e.g.

```<code>class PostListSerializer(serializers.ModelSerializer):
    """
    Main serializers for the writings module
    """
    author = MemberListSerializer(many=False, read_only=True)
    comments = serializers.SerializerMethodField()

    def get_comments(self, instance):
        return instance.comments.count()

    class Meta:
        model = Post
        fields = (
            'id',
            'slug',
            'url',
            'title',
            'description',
            'created',
            'edited',
            'author',
            'comments'
        )
        lookup_field = 'slug'
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }
</code>```

SerializerMethodField is a read-only field that returns the result of a method, generally named get_<field_name>.

Body:
There are a number of questions about serializing GenericRelations in Django Rest Framework however I have a use case where I want to simply return the count of objects in the GenericRelation field only and not serialize them. The documentation and existing questions I can find do not cover this.

I thought it might be as simple as returning the len(value) in a custom Serializer, however that produces the following throw:

object of type 'GenericRelatedObjectManager' has no len()

My failed attempt:

class ObjectCountSerializer(serializers.RelatedField):
    """
    Return the count of related objects.
    """

    def to_representation(self, value):
        return len(value)

class PostListSerializer(serializers.ModelSerializer):
    """
    Main serializers for the writings module
    """
    author = MemberListSerializer(many=False, read_only=True)
    comments = ObjectCountSerializer(read_only=True)

    class Meta:
        model = Post
        fields = (
            'id',
            'slug',
            'url',
            'title',
            'description',
            'created',
            'edited',
            'author',
            'comments'
        )
        lookup_field = 'slug'
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }

How do I simply return the count of objects in the relation?

Body:
I would say a SerializerMethodField would solve this, e.g.

class PostListSerializer(serializers.ModelSerializer):
    """
    Main serializers for the writings module
    """
    author = MemberListSerializer(many=False, read_only=True)
    comments = serializers.SerializerMethodField()

    def get_comments(self, instance):
        return instance.comments.count()

    class Meta:
        model = Post
        fields = (
            'id',
            'slug',
            'url',
            'title',
            'description',
            'created',
            'edited',
            'author',
            'comments'
        )
        lookup_field = 'slug'
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }

SerializerMethodField is a read-only field that returns the result of a method, generally named get_<field_name>.


问:
JQuery Datatable Buttons not working/ not displayed
I have created a view for a datatable (Which is called upon a modal from a link in a datatable in another view), and I intend to put buttons to export the data to Excel, PDF, Print...etc.
I have added the script, but the buttons are not displayed in the final output.

What are the library files that I want to load in order to make the code working with the results that I expect from it?

Note: I have used JQuery 3.1.1

I have tried various methods, also by changing the script library references to no avail. I even tried the download builder from datatables.net, but any of it seemed not working too.

```<code>*The html code*
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="btn btn-default" data-dismiss="modal">Back</button>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
            <h2 class="modal-title">Item</h2>
            <h4>TRANSFER HISTORY</h4>
        </div>
        <div>
            <table id="example" class="display" style="width:100%">
                <tr style="background-color:#b5bbc8">
                    <th>
                        From
                    </th>
                    <th>
                        To
                    </th>
                    <th>
                        Date
                    </th>
                    <th>
                        Cause
                    </th>
                    <th>
                        Updated By
                    </th>
                </tr>

                @foreach (var item in Model)
            {
                    <tr>
                        <td>
                            @Html.DisplayFor(modelItem => item.Center.Name)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.Center1.Name)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.TransferDate)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.TransferCause)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.User.FirstName) @Html.DisplayFor(modelItem => item.User.LastName)
                        </td>
                    </tr>
                }
            </table>
        </div>
    </div>
</div>

*The Buttons script*
<script type="text/javascript">
    $(document).ready(function () {
        $('#example').DataTable({
            dom: 'Bfrtip',
            buttons: [
                'copy', 'csv', 'excel', 'pdf', 'print'
            ]
        });
    });
</script>
</code>```

Update - I just found out what was missing. Actually, it was a reference in the parent view, from which this view is loaded. I fixed it, now everything works fine. Thank you all for your answers and feedback.

答:
as far as I understand, you are trying to initialize datatable inside a modal, so you have to make sure that the data in the modal is loaded correctly before the datatable is initialized, ideally upon the click of the modal button you should call a function in your javascript which makes sure that the data in the modal is loaded correctly and then initializes datatable.

And as far as scripts are concerned, these are the scripts you need to include for datatable buttons to work according to datatable website:-

```<code>https://code.jquery.com/jquery-3.3.1.js
https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js
https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js
https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js
https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js
https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js
https://cdn.datatables.net/buttons/1.5.6/js/buttons.html5.min.js
</code>```

Body:
I have created a view for a datatable (Which is called upon a modal from a link in a datatable in another view), and I intend to put buttons to export the data to Excel, PDF, Print...etc.
I have added the script, but the buttons are not displayed in the final output.

What are the library files that I want to load in order to make the code working with the results that I expect from it?

Note: I have used JQuery 3.1.1

I have tried various methods, also by changing the script library references to no avail. I even tried the download builder from datatables.net, but any of it seemed not working too.

*The html code*

            <button type="button" class="btn btn-default" data-dismiss="modal">Back</button>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Item

TRANSFER HISTORY

                        From

                        To

                        Date

                        Cause

                        Updated By

                @foreach (var item in Model)
            {

                            @Html.DisplayFor(modelItem => item.Center.Name)

                            @Html.DisplayFor(modelItem => item.Center1.Name)

                            @Html.DisplayFor(modelItem => item.TransferDate)

                            @Html.DisplayFor(modelItem => item.TransferCause)

                            @Html.DisplayFor(modelItem => item.User.FirstName) @Html.DisplayFor(modelItem => item.User.LastName)

                }

*The Buttons script*

Update - I just found out what was missing. Actually, it was a reference in the parent view, from which this view is loaded. I fixed it, now everything works fine. Thank you all for your answers and feedback.

Body:
as far as I understand, you are trying to initialize datatable inside a modal, so you have to make sure that the data in the modal is loaded correctly before the datatable is initialized, ideally upon the click of the modal button you should call a function in your javascript which makes sure that the data in the modal is loaded correctly and then initializes datatable.

And as far as scripts are concerned, these are the scripts you need to include for datatable buttons to work according to datatable website:-

https://code.jquery.com/jquery-3.3.1.js
https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js
https://cdn.datatables.net/buttons/1.5.6/js/dataTables.buttons.min.js
https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js
https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js
https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js
https://cdn.datatables.net/buttons/1.5.6/js/buttons.html5.min.js


问:
Matching Patterns for list of tuples
I'm trying to write a fcn that takes in a list of tuple and an expression (I am working on a postfix expression eval). This function should loop through the expression and find the same letter in the tuple. If it's a match then it returns the int value corresponding to that letter in the tuple. When I ran the code below, my program compiled and run but then it was hanging during execution. What did I do wrong?</p>

```<code>    let rec getVar ls exp =

        match ls with
       |head::tl when (fst head) = exp -> printfn "%d" (snd head)
       | _  -> getVar ls exp

    let ls = [("a",5);("b",2);("c",3)]

    let exp = "ab+"
    getVar ls exp
</code>```

答:
Your match must handle three cases.

Empty list -> return some default value (or unit without side effects)

Match found -> return a value or trigger some side effect.

Match not yet found -> keep searching in tail of list.

In your first attempt, you accidentally kept searching in the whole list instead of merely the tail, resulting in an endless recursive loop.
In your second attempt, you instead created an infinite loop in the empty case.
Below is one example of how you might write the recursive function.

```<code> let rec getVar ls exp =
     match ls with
     |[] -> None
     |head::tail when (fst head) = exp -> Some <| sprintf "%d" (snd head)
     |head::tail  -> getVar tail exp

 let ls = [("a",5);("b",2);("c",3)]

 let result1 = getVar ls "ab+"   // result = None
 let result2 = getVar ls "b"     // result = Some "2"
</code>```

Title: Matching Patterns for list of tuples

Body:
I'm trying to write a fcn that takes in a list of tuple and an expression (I am working on a postfix expression eval). This function should loop through the expression and find the same letter in the tuple. If it's a match then it returns the int value corresponding to that letter in the tuple. When I ran the code below, my program compiled and run but then it was hanging during execution. What did I do wrong?

    let rec getVar ls exp =

        match ls with
       |head::tl when (fst head) = exp -> printfn "%d" (snd head)
       | _  -> getVar ls exp

    let ls = [("a",5);("b",2);("c",3)]

    let exp = "ab+"
    getVar ls exp

Body:
Your match must handle three cases.

Empty list -> return some default value (or unit without side effects)

Match found -> return a value or trigger some side effect.

Match not yet found -> keep searching in tail of list.

In your first attempt, you accidentally kept searching in the whole list instead of merely the tail, resulting in an endless recursive loop.
In your second attempt, you instead created an infinite loop in the empty case.
Below is one example of how you might write the recursive function.

 let rec getVar ls exp =
     match ls with
     |[] -> None
     |head::tail when (fst head) = exp -> Some <| sprintf "%d" (snd head)
     |head::tail  -> getVar tail exp

 let ls = [("a",5);("b",2);("c",3)]

 let result1 = getVar ls "ab+"   // result = None
 let result2 = getVar ls "b"     // result = Some "2"