问:
kapt generated code not available during compilation phase
I have written a code generator using kapt, and am using it in a project compiling kotlin with maven.

I find that the kapt generator is invoked after Kotlin's compile phase, which prevents me from using the generated code within kotlin in the same project.

However, if I reference the generated classes from within Java in the same project, it works fine.  This is because the java compilation phase comes after kotlin's generation phase.

I've specified the kapt goal before Kotlin's compilation goal within the maven config, (as mentioned in the docs) but it doesn't seem to make a difference:

```<code>        <plugin>
            <artifactId>kotlin-maven-plugin</artifactId>
            <groupId>org.jetbrains.kotlin</groupId>
            <version>${kotlin.version}</version>
            <executions>
                <execution>
                    <id>kapt</id>
                    <goals>
                        <goal>kapt</goal>
                    </goals>
                    <configuration>
                        <sourceDirs>
                            <sourceDir>src/main/java</sourceDir>
                        </sourceDirs>
                        <annotationProcessorPaths>
                            <annotationProcessorPath>
                                <groupId>lang.taxi</groupId>
                                <artifactId>taxi-annotation-processor</artifactId>
                                <version>${taxi.version}</version>
                            </annotationProcessorPath>
                        </annotationProcessorPaths>
                    </configuration>
                </execution>
                <execution>
                    <id>compile</id>
                    <goals> <goal>compile</goal> </goals>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <goals> <goal>test-compile</goal> </goals>
                    <configuration>
                        <sourceDirs>
                            <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                            <sourceDir>${project.basedir}/src/test/java</sourceDir>
                        </sourceDirs>
                    </configuration>
                </execution>
            </executions>
        </plugin>
</code>```

Is it possible to configure Kotlin to allow me to use the generated code from Kotlin in the same project?

答: You can use gradle DAG to solve your problem simply by making compile/assemble task depend on kapt task. I know how to do this in android if that  help you please let me know and I will post the code right after.</p>

Body:
I have written a code generator using kapt, and am using it in a project compiling kotlin with maven.

I find that the kapt generator is invoked after Kotlin's compile phase, which prevents me from using the generated code within kotlin in the same project.

However, if I reference the generated classes from within Java in the same project, it works fine.  This is because the java compilation phase comes after kotlin's generation phase.

I've specified the kapt goal before Kotlin's compilation goal within the maven config, (as mentioned in the docs) but it doesn't seem to make a difference:

        <plugin>
            <artifactId>kotlin-maven-plugin</artifactId>
            <groupId>org.jetbrains.kotlin</groupId>
            <version>${kotlin.version}</version>
            <executions>
                <execution>
                    <id>kapt</id>
                    <goals>
                        <goal>kapt</goal>
                    </goals>
                    <configuration>
                        <sourceDirs>
                            <sourceDir>src/main/java</sourceDir>
                        </sourceDirs>
                        <annotationProcessorPaths>
                            <annotationProcessorPath>
                                <groupId>lang.taxi</groupId>
                                <artifactId>taxi-annotation-processor</artifactId>
                                <version>${taxi.version}</version>
                            </annotationProcessorPath>
                        </annotationProcessorPaths>
                    </configuration>
                </execution>
                <execution>
                    <id>compile</id>
                    <goals> <goal>compile</goal> </goals>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <goals> <goal>test-compile</goal> </goals>
                    <configuration>
                        <sourceDirs>
                            <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                            <sourceDir>${project.basedir}/src/test/java</sourceDir>
                        </sourceDirs>
                    </configuration>
                </execution>
            </executions>
        </plugin>

Is it possible to configure Kotlin to allow me to use the generated code from Kotlin in the same project?


来源: stackexchange

问:
i was trying to create a command to remind members not to spam but i am having an error: TypeError: Cannot read property 'send' of undefined
this is the code where am having the error.

```<code>if (sniper.enableremind == true) {
    setInterval(function() {
        return client.channels.get(sniper.remind[Math.floor(Math.random() * sniper.remind.length)]).send(sniper.words[Math.floor(Math.random() * sniper.words.length)]);
    }, sniper.remindtime);
}
</code>```

and this is main file Sniper.js

```<code>const client = new (require('discord.js')).Client();

// Customisable stuff

var sniper = {};

sniper.instance = 1;
sniper.enablelogs = true;
sniper.enableremind = true;
sniper.spawn = 'chanel id to read';
sniper.remind = ['reminder channel id'];
sniper.remindtime = 5000;
sniper.logs = 'channel id';
sniper.botprefix = '>';
sniper.playing = 'Fortnite';
sniper.token = 'token';
sniper.owner = 'id';

// Text to remind

sniper.words = [
    "You are using commands for a long time",
    "please cooldown for sometime"
];

// Logging in to discord

client.login(sniper.token);

client.on('ready', () => {
    client.user.setActivity(sniper.playing);
    client.user.setStatus('online');
});

// Send text to remind server members

if (sniper.enableremind == true) {
    setInterval(function() {
        return client.channels.get(sniper.remind[Math.floor(Math.random() * sniper.remind.length)]).send(sniper.words[Math.floor(Math.random() * sniper.words.length)]);
    }, sniper.remindtime);
}
</code>```

答:
Recently, discord.js went through a major update, v12. In that version, .channels is a ChannelManager, which doesn't implement .get like Collections did. To get a channel, you now have to .fetch it instead:

client.channels.fetch(sniper.remind[Math.floor(Math.random() * sniper.remind.length)]).send(sniper.words[Math.floor(Math.random() * sniper.words.length)])
```

ContentLicense: CC BY-SA 4.0

Body:
this is the code where am having the error.

if (sniper.enableremind == true) {
    setInterval(function() {
        return client.channels.get(sniper.remind[Math.floor(Math.random() * sniper.remind.length)]).send(sniper.words[Math.floor(Math.random() * sniper.words.length)]);
    }, sniper.remindtime);
}

and this is main file Sniper.js

const client = new (require('discord.js')).Client();

// Customisable stuff

var sniper = {};

sniper.instance = 1;
sniper.enablelogs = true;
sniper.enableremind = true;
sniper.spawn = 'chanel id to read';
sniper.remind = ['reminder channel id'];
sniper.remindtime = 5000;
sniper.logs = 'channel id';
sniper.botprefix = '>';
sniper.playing = 'Fortnite';
sniper.token = 'token';
sniper.owner = 'id';

// Text to remind

sniper.words = [
    "You are using commands for a long time",
    "please cooldown for sometime"
];

// Logging in to discord

client.login(sniper.token);

client.on('ready', () => {
    client.user.setActivity(sniper.playing);
    client.user.setStatus('online');
});

// Send text to remind server members

if (sniper.enableremind == true) {
    setInterval(function() {
        return client.channels.get(sniper.remind[Math.floor(Math.random() * sniper.remind.length)]).send(sniper.words[Math.floor(Math.random() * sniper.words.length)]);
    }, sniper.remindtime);
}


问:
How to add bytes together and validate them against the checksum in python
How do you calculate the checksum of incoming bytes to see if it is a valid packet?
Currently I am reading the bytes and decoding them and receiving the information but before I do that I would like to be able to validate it against the checksum to make sure I do not get any invalid/corrupt packets.

Here is what I currently have

```<code>def batteryConnect(port, baudrate):
    # establishing a serial connection
    ser = serial.Serial(port=port, baudrate= baudrate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,timeout=3)
    return ser

class VictronBmv700:

    def __init__(self,port,baudrate):
        self.port = port
        self.baudrate = baudrate
        self.parameterDict = dict.fromkeys(["PID","V","I","P","CE","SOC","TTG","Alarm","Relay","AR","BMV","FW","H1","H2","H3",
                                  "H4","H5","H6","H7","H8","H9","H10","H11","H12","H17","H18"])

    def getBMVInfo(self):

        bmvdata = batteryConnect(self.port,self.baudrate)

        #getting the data
        bmvdata.flushInput()

        #getting the message then splitting the key, value pairs
        while True:
            print(bmvdata.readline())

            message = bmvdata.readline().decode(encoding='utf-8',errors='ignore')

            #splitting on tabs
            message_parts = message.split('\t')

            if len(message_parts) > 1:
                key = message_parts[0]
                value = message_parts[1].rstrip()  #stripping \r\n after the value

                #updating deictionary based on keys and their values.
                self.parameterDict[key] = value

if __name__ == "__main__":
    print("BATTERY MONITOR")
    bmv700 = VictronBmv700("COM17", 19200)
    bmv700.getBMVInfo()

</code>```

Which starts outputting the following (from the print(bmvdata.readline()) )

```<code>b'\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd7\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd6\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
</code>```

How would I check the incoming bytes against the checksum then continue to decode after validation?

EDIT
Sometimes I get different checksum values as below.
Here are two additional times I ran the code.

```<code>b'\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd7\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
</code>```

Second run

```<code>b'\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25549\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25549\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
</code>```

EDIT
Ran the following code

```<code>current_block = []
# it's unfortunate that lines start with `\r\n` rather than end with it
# we will read the first empty line separatey, and then include these
# 2 characters in the last line that is read
message = bmvdata.readline()
while True:
    # Note that we cannot decode yet, since the Checksum value may not be a valid utf8 character
    message = bmvdata.readline()

    # we save the message in the current block before any preprocessing
    current_block.append(message)

    #splitting on tabs (as bytes !!)
    message_parts = message.split(b'\t')

    if len(message_parts) > 1:
        key = message_parts[0].decode('utf8')  # here it is safe to decode the key
        value = message_parts[1].rstrip()  #stripping \r\n after the value

    if key == 'Checksum':
        block_chars = b''.join(current_block)
        checksum = sum(block_chars) % 256
        print('Retrieved  checksum', value[-1])
        print('Calculated checksum', checksum)
        print('----')

        # reset the block
        current_block = []
</code>```

output

```<code>Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
</code>```

答:
It seems that the poster is trying to read data from a BMV700 battery monitor. Reading the papers here, we see that this communicates over the Serial interface using a text protocol:

2 TextProtocol

When no VE.Direct queries are sent to the device, the charger periodically sends human readable (TEXT) data to the serial port. See the "VE.Direct Protocol" document for a detailed description of the contents and availability of the information

Excerpt from the HEX protocol (BMV-7xx-HEX-Protocol-public.pdf)

Looking into the specification of the TEXT protocol (VE.Direct-Protocol-3.28.pdf), we find:

Message format

The device transmits blocks of data at 1 second intervals. Each field is sent using the following format:

```<code><Newline><Field-Label><Tab><Field-Value>
</code>```

The identifiers are defined as follows:

```<code>+---------------+--------------------------------------------------------------------------------------+
| Identifier    | Meaning                                                                              |
+===============+======================================================================================+
| <Newline>     | A carriage return followed by a line feed (0x0D, 0x0A).                              |
+---------------+--------------------------------------------------------------------------------------+
| <Field-Label> | An arbitrary length label that identifies the field.                                 |
|               | Where applicable, this will be the same as the label that is used on the LCD.        |
+---------------+--------------------------------------------------------------------------------------+
| <Tab>         | A horizontal tab (0x09).                                                             |
+---------------+--------------------------------------------------------------------------------------+
| <Field-Value> | The ASCII formatted value of this field.                                             |
|               | The number of characters transmitted depends on the magnitude and sign of the value. |
+---------------+--------------------------------------------------------------------------------------+
</code>```

This corrsponds to the data you're printing, with one exception: the line starts with \r\b, it doesn't end with them.

Then, the file gives details about the Checksum:

Data integrity

The statistics are grouped in blocks with a checksum appended. The last field in a block will always be “Checksum”. The value is a single byte, and will not necessarily be a printable ASCII character. The modulo 256 sum of all bytes in a block will equal 0 if there were no transmission errors. Multiple blocks are sent containing different fields.

So, in the excerpt that you posted as output, you have two complete blocks, and an incomplete one, as the last block is missing the Checksum.

```<code>block = (b'\r\nH2\t0\r\n'
    b'H4\t0\r\n'
    b'H6\t-9001\r\n'
    b'H8\t28403\r\n'
    b'H10\t0\r\n'
    b'H12\t0\r\n'
    b'H18\t87\r\n'
    b'PID\t0x203\r\n'
    b'I\t0\r\n'
    b'CE\t0\r\n'
    b'TTG\t-1\r\n'
    b'Relay\tOFF\r\n'
    b'BMV\t700\r\n'
    b'Checksum\t\xd6')
</code>```

Note that I have added the \r\n at the beginning, and removed them from the end of the block, such that the last byte is the block's checksum.

Now, we can calculate the checksum of the block:

```<code>>>> sum(block) % 256
213
</code>```

This should have been zero. So, there may be some transmission problems, or they may be calculating the checksum differently from what they say in the docs.

Edit after new data.

Here is the code that I have used to inspect all the blocks that you have posted:

```<code>current_block = []
# it's unfortunate that lines start with `\r\n` rather than end with it
# we will read the first empty line separatey, and then include these
# 2 characters in the last line that is read
message = bmvdata.readline()
while True:
    # Note that we cannot decode yet, since the Checksum value may not be a valid utf8 character
    message = bmvdata.readline()

    # we save the message in the current block before any preprocessing
    current_block.append(message)

    #splitting on tabs (as bytes !!)
    message_parts = message.split(b'\t')

    if len(message_parts) > 1:
        key = message_parts[0].decode('utf8')  # here it is safe to decode the key
        value = message_parts[1].rstrip()  #stripping \r\n after the value

    if key == 'Checksum':
        block_chars = b''.join(current_block)
        checksum = sum(block_chars) % 256
        print('Retrieved  checksum', value[-1])
        print('Calculated checksum', checksum)
        print('----')

        # reset the block
        current_block = []
</code>```

It is weird that for the first run you always get the calculated value equal retrieved + 1, but not in the second run. So, there may be some transmission problems.

Body:
How do you calculate the checksum of incoming bytes to see if it is a valid packet?
Currently I am reading the bytes and decoding them and receiving the information but before I do that I would like to be able to validate it against the checksum to make sure I do not get any invalid/corrupt packets.

Here is what I currently have

def batteryConnect(port, baudrate):
    # establishing a serial connection
    ser = serial.Serial(port=port, baudrate= baudrate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,timeout=3)
    return ser

class VictronBmv700:

    def __init__(self,port,baudrate):
        self.port = port
        self.baudrate = baudrate
        self.parameterDict = dict.fromkeys(["PID","V","I","P","CE","SOC","TTG","Alarm","Relay","AR","BMV","FW","H1","H2","H3",
                                  "H4","H5","H6","H7","H8","H9","H10","H11","H12","H17","H18"])

    def getBMVInfo(self):

        bmvdata = batteryConnect(self.port,self.baudrate)

        #getting the data
        bmvdata.flushInput()

        #getting the message then splitting the key, value pairs
        while True:
            print(bmvdata.readline())

            message = bmvdata.readline().decode(encoding='utf-8',errors='ignore')

            #splitting on tabs
            message_parts = message.split('\t')

            if len(message_parts) > 1:
                key = message_parts[0]
                value = message_parts[1].rstrip()  #stripping \r\n after the value

                #updating deictionary based on keys and their values.
                self.parameterDict[key] = value

if __name__ == "__main__":
    print("BATTERY MONITOR")
    bmv700 = VictronBmv700("COM17", 19200)
    bmv700.getBMVInfo()

Which starts outputting the following (from the print(bmvdata.readline()) )

b'\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd7\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd6\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'

How would I check the incoming bytes against the checksum then continue to decode after validation?

EDIT
Sometimes I get different checksum values as below.
Here are two additional times I ran the code.

b'\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd7\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd8\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'
b'PID\t0x203\r\n'
b'I\t0\r\n'
b'CE\t0\r\n'
b'TTG\t-1\r\n'
b'Relay\tOFF\r\n'
b'BMV\t700\r\n'
b'Checksum\t\xd0\r\n'
b'H2\t0\r\n'
b'H4\t0\r\n'
b'H6\t-9001\r\n'
b'H8\t28403\r\n'
b'H10\t0\r\n'
b'H12\t0\r\n'
b'H18\t87\r\n'

Second run

b'\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25549\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25549\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'
b'H1\t-6254\r\n'
b'H3\t0\r\n'
b'H5\t0\r\n'
b'H7\t-10\r\n'
b'H9\t0\r\n'
b'H11\t0\r\n'
b'H17\t20\r\n'
b'Checksum\tT\r\n'
b'V\t25548\r\n'
b'P\t0\r\n'
b'SOC\t1000\r\n'
b'Alarm\tOFF\r\n'
b'AR\t0\r\n'
b'FW\t0310\r\n'

EDIT
Ran the following code

current_block = []
# it's unfortunate that lines start with `\r\n` rather than end with it
# we will read the first empty line separatey, and then include these
# 2 characters in the last line that is read
message = bmvdata.readline()
while True:
    # Note that we cannot decode yet, since the Checksum value may not be a valid utf8 character
    message = bmvdata.readline()

    # we save the message in the current block before any preprocessing
    current_block.append(message)

    #splitting on tabs (as bytes !!)
    message_parts = message.split(b'\t')

    if len(message_parts) > 1:
        key = message_parts[0].decode('utf8')  # here it is safe to decode the key
        value = message_parts[1].rstrip()  #stripping \r\n after the value

    if key == 'Checksum':
        block_chars = b''.join(current_block)
        checksum = sum(block_chars) % 256
        print('Retrieved  checksum', value[-1])
        print('Calculated checksum', checksum)
        print('----')

        # reset the block
        current_block = []

output

Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 220
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------
Retrieved checksum 219
Calculated checksum 0
-------
Retrieved checksum 84
Calculated checksum 0
-------

Body:
It seems that the poster is trying to read data from a BMV700 battery monitor. Reading the papers here, we see that this communicates over the Serial interface using a text protocol:

2 TextProtocol

When no VE.Direct queries are sent to the device, the charger periodically sends human readable (TEXT) data to the serial port. See the "VE.Direct Protocol" document for a detailed description of the contents and availability of the information

Excerpt from the HEX protocol (BMV-7xx-HEX-Protocol-public.pdf)

Looking into the specification of the TEXT protocol (VE.Direct-Protocol-3.28.pdf), we find:

Message format

The device transmits blocks of data at 1 second intervals. Each field is sent using the following format:

<Newline><Field-Label><Tab><Field-Value>

The identifiers are defined as follows:

+---------------+--------------------------------------------------------------------------------------+
| Identifier    | Meaning                                                                              |
+===============+======================================================================================+
| <Newline>     | A carriage return followed by a line feed (0x0D, 0x0A).                              |
+---------------+--------------------------------------------------------------------------------------+
| <Field-Label> | An arbitrary length label that identifies the field.                                 |
|               | Where applicable, this will be the same as the label that is used on the LCD.        |
+---------------+--------------------------------------------------------------------------------------+
| <Tab>         | A horizontal tab (0x09).                                                             |
+---------------+--------------------------------------------------------------------------------------+
| <Field-Value> | The ASCII formatted value of this field.                                             |
|               | The number of characters transmitted depends on the magnitude and sign of the value. |
+---------------+--------------------------------------------------------------------------------------+

This corrsponds to the data you're printing, with one exception: the line starts with \r\b, it doesn't end with them.

Then, the file gives details about the Checksum:

Data integrity

The statistics are grouped in blocks with a checksum appended. The last field in a block will always be “Checksum”. The value is a single byte, and will not necessarily be a printable ASCII character. The modulo 256 sum of all bytes in a block will equal 0 if there were no transmission errors. Multiple blocks are sent containing different fields.

So, in the excerpt that you posted as output, you have two complete blocks, and an incomplete one, as the last block is missing the Checksum.

block = (b'\r\nH2\t0\r\n'
    b'H4\t0\r\n'
    b'H6\t-9001\r\n'
    b'H8\t28403\r\n'
    b'H10\t0\r\n'
    b'H12\t0\r\n'
    b'H18\t87\r\n'
    b'PID\t0x203\r\n'
    b'I\t0\r\n'
    b'CE\t0\r\n'
    b'TTG\t-1\r\n'
    b'Relay\tOFF\r\n'
    b'BMV\t700\r\n'
    b'Checksum\t\xd6')

Note that I have added the \r\n at the beginning, and removed them from the end of the block, such that the last byte is the block's checksum.

Now, we can calculate the checksum of the block:

>>> sum(block) % 256
213

This should have been zero. So, there may be some transmission problems, or they may be calculating the checksum differently from what they say in the docs.

Edit after new data.

Here is the code that I have used to inspect all the blocks that you have posted:

current_block = []
# it's unfortunate that lines start with `\r\n` rather than end with it
# we will read the first empty line separatey, and then include these
# 2 characters in the last line that is read
message = bmvdata.readline()
while True:
    # Note that we cannot decode yet, since the Checksum value may not be a valid utf8 character
    message = bmvdata.readline()

    # we save the message in the current block before any preprocessing
    current_block.append(message)

    #splitting on tabs (as bytes !!)
    message_parts = message.split(b'\t')

    if len(message_parts) > 1:
        key = message_parts[0].decode('utf8')  # here it is safe to decode the key
        value = message_parts[1].rstrip()  #stripping \r\n after the value

    if key == 'Checksum':
        block_chars = b''.join(current_block)
        checksum = sum(block_chars) % 256
        print('Retrieved  checksum', value[-1])
        print('Calculated checksum', checksum)
        print('----')

        # reset the block
        current_block = []

It is weird that for the first run you always get the calculated value equal retrieved + 1, but not in the second run. So, there may be some transmission problems.


问:
cellForRowAtIndexPath is not called sometimes after calling numberOfRowsInSection on calling reloadData
I have a simple application where I have a table view & depending on the callback with array I reload the table data using reloadData method. Initially for first 5-10 times of loading this table view works without any problem. After playing with the application for sometimes I noticed that the table view is blank because of the reason that cellForRowAtIndexPath is not called by the framework. I verified that datasource & delegate is set properly & numberOfRowsInSection is returning a valid positive number. Once I see the blank table view then I can see this blank view repeatedly until I exit the application. I do not get any error or warnings in the console. I tried to tweak the array but to no avail.

Here is the code:

```<code>- (void)notifyArrayLoaded:(NSArray *)arr {
    NSUInteger capacity = [arr count];
    _tbDataArray = [[NSMutableArray alloc] initWithCapacity:capacity];

    // _tbDataArray is filled with the data from arr

    // Reload the table data
    [_tableView reloadData];
}
</code>```

Any clue will be highly appreciated.

Thanks in advance.
Sumit

Hi DeanWombourne, I do not have viewDidUnLoad method but I have viewWillDisAppear method which I am posting it here.

```<code>- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
    [[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
    [self.navigationController setNavigationBarHidden:NO animated:NO];

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    UIView *view = [window.subviews objectAtIndex:0];

    view.transform = CGAffineTransformIdentity;
    view.transform = CGAffineTransformMakeRotation(0);
    view.bounds = CGRectMake(0.0, 0.0, 320, 480);
}
</code>```

This is the logs of tableView as logged.

```<code>[numberOfSectionsInTableView:] [Line 223] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
[tableView:numberOfRowsInSection:] [Line 229] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
<UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
[numberOfSectionsInTableView:] [Line 223] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
[tableView:numberOfRowsInSection:] [Line 229] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
</code>```

答:
go to the header file of the viewcontroller and add (IBOutlet) to the tableView member.
then connect throught interfaceb</p>

ContentLicense: CC BY-SA 3.0

Body:
I have a simple application where I have a table view & depending on the callback with array I reload the table data using reloadData method. Initially for first 5-10 times of loading this table view works without any problem. After playing with the application for sometimes I noticed that the table view is blank because of the reason that cellForRowAtIndexPath is not called by the framework. I verified that datasource & delegate is set properly & numberOfRowsInSection is returning a valid positive number. Once I see the blank table view then I can see this blank view repeatedly until I exit the application. I do not get any error or warnings in the console. I tried to tweak the array but to no avail.

Here is the code:

- (void)notifyArrayLoaded:(NSArray *)arr {
    NSUInteger capacity = [arr count];
    _tbDataArray = [[NSMutableArray alloc] initWithCapacity:capacity];

    // _tbDataArray is filled with the data from arr

    // Reload the table data
    [_tableView reloadData];
}

Any clue will be highly appreciated.

Thanks in advance.
Sumit

Hi DeanWombourne, I do not have viewDidUnLoad method but I have viewWillDisAppear method which I am posting it here.

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
    [[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
    [self.navigationController setNavigationBarHidden:NO animated:NO];

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    UIView *view = [window.subviews objectAtIndex:0];

    view.transform = CGAffineTransformIdentity;
    view.transform = CGAffineTransformMakeRotation(0);
    view.bounds = CGRectMake(0.0, 0.0, 320, 480);
}

This is the logs of tableView as logged.

[numberOfSectionsInTableView:] [Line 223] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
[tableView:numberOfRowsInSection:] [Line 229] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
<UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
[numberOfSectionsInTableView:] [Line 223] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>
[tableView:numberOfRowsInSection:] [Line 229] <UITableView: 0xa5fc00; frame = (0 0; 320 0); clipsToBounds = YES; layer = <CALayer: 0x4830b0>; contentOffset: {0, 0}>


问:
Rails: Load default image if image_tag cannot load image from url
I want to render a default image if image_tag cannot load an image from a url:

So if image_tag cannot load image from url:

```<code><%= image_tag 'https://something.com/image.jpg' %>
</code>```

then render default:

```<code><%= image_tag image_url("default.png")
</code>```

答:
A pure Ruby on Rails solution:</p>

```<code><%= image_tag 'devices/my-device.png' rescue image_tag 'devices/unknow-device.png' %>
</code>```

Body:
I want to render a default image if image_tag cannot load an image from a url:

So if image_tag cannot load image from url:

<%= image_tag 'https://something.com/image.jpg' %>

then render default:

<%= image_tag image_url("default.png")

Body:
A pure Ruby on Rails solution:

<%= image_tag 'devices/my-device.png' rescue image_tag 'devices/unknow-device.png' %>


问:
How to get embedding from bert finetuned model?
I have finedtuned 'bert-base-uncased' model using transformer and torch which gave me pytorch_model.bin, vocab.txt and other files as output.
After loading the model how to I get embedding for complete vocab, like a matrix which maps every word to its embedding vector </p>

答:
I recommend to use Huggingface, they make it very easy to use and train all Transformer model variants.

To get the embedding from a BERT fine-tuned model, you could use BertModel.set_input_embeddings().


问:
regex to add a limit of 10 digits with decimal value having no limit
I want to apply a validation where I need a limit of 10 digits on value but the value after decimal has no limit.

Like this
1000000000.2121
The value before decimal should be less than 10 digits.
I am trying this regex
^(10|\d)(\.\d{1,2})?$
 But By this, I only add decimal digits with a limit of two. How can I achieve this?

答:
The value before decimal should be less than 10 digits

This pattern permits zero to 9 digits then optionally allows a decimal point followed by unlimited digits.

If your requirement is to have at least one digit before the decimal, then change {0-9} to {1,9}.

If your requirement is to have between zero and ten digits before the decimal, then change {0,9} to {0,10}.

Code: (Demo)

```<code>$tests = [
    '12345678901',
    '1234567890',
    '123456789',
    '1234567890.1',
    '1234567.8901',
    '1234.5678901',
    '1.2345678901',
    '.12345678901',
];

foreach ($tests as $test) {
    var_export([$test, (bool)preg_match('~^\d{0,9}(?:\.\d+)?$~', $test)]);
    echo "\n";
}
</code>```

Output:

```<code>array (
  0 => '12345678901',
  1 => false,
)
array (
  0 => '1234567890',
  1 => false,
)
array (
  0 => '123456789',
  1 => true,
)
array (
  0 => '1234567890.1',
  1 => false,
)
array (
  0 => '1234567.8901',
  1 => true,
)
array (
  0 => '1234.5678901',
  1 => true,
)
array (
  0 => '1.2345678901',
  1 => true,
)
array (
  0 => '.12345678901',
  1 => true,
)
</code>```

Body:
The value before decimal should be less than 10 digits

This pattern permits zero to 9 digits then optionally allows a decimal point followed by unlimited digits.

If your requirement is to have at least one digit before the decimal, then change {0-9} to {1,9}.

If your requirement is to have between zero and ten digits before the decimal, then change {0,9} to {0,10}.

Code: (Demo)

$tests = [
    '12345678901',
    '1234567890',
    '123456789',
    '1234567890.1',
    '1234567.8901',
    '1234.5678901',
    '1.2345678901',
    '.12345678901',
];

foreach ($tests as $test) {
    var_export([$test, (bool)preg_match('~^\d{0,9}(?:\.\d+)?$~', $test)]);
    echo "\n";
}

Output:

array (
  0 => '12345678901',
  1 => false,
)
array (
  0 => '1234567890',
  1 => false,
)
array (
  0 => '123456789',
  1 => true,
)
array (
  0 => '1234567890.1',
  1 => false,
)
array (
  0 => '1234567.8901',
  1 => true,
)
array (
  0 => '1234.5678901',
  1 => true,
)
array (
  0 => '1.2345678901',
  1 => true,
)
array (
  0 => '.12345678901',
  1 => true,
)


问:
Meaning of ascii(my_field) & 8 <> 8 condition in SQL request
I'm working on a SQL script that contains this condition :

```<code>select *
from my_table
where ascii(my_field) & 8 <> 8;
</code>```

What does it mean?

I would like to implement this request on a PySpark script but if I don't understand the meaning of this condition it will be hard to do it.

PS: the SQL script is a .hql

Thank you all :)

答:
it mean where the ascii code of the value is not 8 (backspace)

<> is like x > y || x < y that equals to x!=y. (<> mean not equal of numbers)

& it is 'AND' operation on the bit of the value (8&8=8).

This sql is equal to:

```<code>SELECT * FROM my_table where my_field != ' '
</code>```

Body:
I'm working on a SQL script that contains this condition :

select *
from my_table
where ascii(my_field) & 8 <> 8;

What does it mean?

I would like to implement this request on a PySpark script but if I don't understand the meaning of this condition it will be hard to do it.

PS: the SQL script is a .hql

Thank you all :)

Body:
it mean where the ascii code of the value is not 8 (backspace)

<> is like x > y || x < y that equals to x!=y. (<> mean not equal of numbers)

& it is 'AND' operation on the bit of the value (8&8=8).

This sql is equal to:

SELECT * FROM my_table where my_field != ' '


问:
updating an array in state
I am attempting to update an object of names in the state before passing it as a props to another component.

```<code>// some code above

this.state = {
    // some other states
    playerName: {
        player1Name: 'Default Player 1 Name',
        player2Name: 'Default Player 2 Name',
        player3Name: 'Default Player 3 Name'
    }
};
this.nameChange = this.nameChange.bind(this);

nameChange(e){
    this.setState( prevState => ({
        playerName: {
            ...prevState.playerName,
            [e.target.id]: e.target.value
        }
    })
}

render(){
    return(
        <div>
            <input type='name' id='player1Name' onChange={this.nameChange}/>
            <input type='name' id='player2Name' onChange={this.nameChange}/>
            <input type='name' id='player3Name' onChange={this.nameChange}/>
        </div>
    )
}

</code>```

However, it returns the error of unable to read 'id' of null and 'value' of null

答:
you need use name in input and e.target.name in handler. Please check this example:

```<code>import React from "react";

export default class PlayerName extends React.Component {
    state = {
        // some other states
        playerName: {
            player1Name: 'Default Player 1 Name',
            player2Name: 'Default Player 2 Name',
            player3Name: 'Default Player 3 Name'
        }
    };

    nameChange = (e) => {
        const name = e.target.name;
        const value = e.target.value;

         this.setState(prevState => ({
            playerName: {
                ...prevState.playerName,
                [name]: value
            }
        }));
        console.log( this.state);
    };

    render() {
        return (
            <div>
                <input type='name' name='player1Name' onChange={this.nameChange}/>
                <input type='name' name='player2Name' onChange={this.nameChange}/>
                <input type='name' name='player3Name' onChange={this.nameChange}/>
            </div>
        )
    }
}
</code>```

Title: updating an array in state

Body:
I am attempting to update an object of names in the state before passing it as a props to another component.

// some code above

this.state = {
    // some other states
    playerName: {
        player1Name: 'Default Player 1 Name',
        player2Name: 'Default Player 2 Name',
        player3Name: 'Default Player 3 Name'
    }
};
this.nameChange = this.nameChange.bind(this);

nameChange(e){
    this.setState( prevState => ({
        playerName: {
            ...prevState.playerName,
            [e.target.id]: e.target.value
        }
    })
}

render(){
    return(

            <input type='name' id='player1Name' onChange={this.nameChange}/>
            <input type='name' id='player2Name' onChange={this.nameChange}/>
            <input type='name' id='player3Name' onChange={this.nameChange}/>

    )
}

However, it returns the error of unable to read 'id' of null and 'value' of null

Body:
you need use name in input and e.target.name in handler. Please check this example:

import React from "react";

export default class PlayerName extends React.Component {
    state = {
        // some other states
        playerName: {
            player1Name: 'Default Player 1 Name',
            player2Name: 'Default Player 2 Name',
            player3Name: 'Default Player 3 Name'
        }
    };

    nameChange = (e) => {
        const name = e.target.name;
        const value = e.target.value;

         this.setState(prevState => ({
            playerName: {
                ...prevState.playerName,
                [name]: value
            }
        }));
        console.log( this.state);
    };

    render() {
        return (
            <div>
                <input type='name' name='player1Name' onChange={this.nameChange}/>
                <input type='name' name='player2Name' onChange={this.nameChange}/>
                <input type='name' name='player3Name' onChange={this.nameChange}/>
            </div>
        )
    }
}


问:
What should be change in the "gender" part of the coding I have done below?
In the code below keeps on looping where entering 1 will lead in the void main() function and inside it, there is "gender" information. However, the gender output always got skipped over right after I type the date.

The "Enter your gender(Male/Female): " part got skipped

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void entry() {
    FILE *fpointer;
    char name[20], gender[20], op, option;
    int visit_ID, phone_number, service_needed, change_service, date;
    float service_fee, payment_made, changes, change_service_fee;

    printf("\n\nEnter information:\n");
    printf("\nEnter name: ");
    scanf("%s", name);
    printf("\n\nEnter your ID number(Number only): ");
    scanf("%d", &visit_ID);
    printf("\n\nEnter today date in dd-mm-yy: ");
    scanf("%d", &date);
    printf("\n\nEnter your gender(Male/Female): ");
    scanf("%s", &gender);
    printf("\n\nEnter your phone number: ");
    scanf("%d", &phone_number);
    printf("\n\nDone registered\n\n");

    if ((fpointer = fopen("visitdetails.txt", "a")) == NULL) {
        perror("Write");
        exit(1);
    }
    fprintf(fpointer, "Visit ID = %d", visit_ID);
    fprintf(fpointer, "\nCustomer name = %s", name);
    fprintf(fpointer, "\nLast visit date : %d", date);
    fprintf(fpointer, "\nLast Service type repaired: %d", service_needed);
    fscanf(fpointer, "%d", service_needed);
    fprintf(fpointer, "\nLast Service fee: %.2f", service_fee);
    fprintf(fpointer, "\nLast payment: %.2f", payment_made);
    printf("\n\nRecord Written Successfully\n\n!!!");
    fclose(fpointer);
}

void Repair() {
    char name[20], gender[20], op, option;
    int visit_ID, phone_number, service_needed, date;
    float service_fee, payment_made, changes, change_service_fee;
    FILE *Welcome;

    Welcome = fopen("visitdetails.txt", "r");
    printf("\nWhich service type do you need(1-8)? ");
    scanf("%d", &service_needed);

    switch (service_needed) {
      case 1:
        printf("\nThe cost of it will be 30RM for Normal and 50RM for Urgent(type the cost): ");
        scanf("%f", &service_fee);
        break;

      case 2:
        printf("\nThe cost of it will be 40RM for Normal and 70RM for Urgent(type the cost): ");
        scanf("%f", &service_fee);
        break;

      case 3:
        printf("\nThe cost of it will be 330RM for Normal and 430RM for Urgent(type the cost): ");
        scanf("%f", &service_fee);
        break;

      case 4:
        printf("\nThe cost of it will be 160RM for Normal and 200RM for Urgent(type the cost): ");
        scanf("%f", &service_fee);
        break;

      case 5:
        printf("\nThe cost of it will be 180RM for Normal and 210RM for Urgent(type the cost): ");
        scanf("%f", &service_fee);
        break;

      case 6:
        printf("\nThe cost of it will be 50RM for Normal and 80RM for Urgent(type the cost): ", service_fee);
        scanf("%f", &service_fee);
        break;

      case 7:
        printf("\nThe cost of it will be 100RM for Normal and 150RM for Urgent(type the cost): ", service_fee);
        scanf("%f", &service_fee);
        break;

      case 8:
        printf("\nThe cost of it will be 50RM for Normal and 75RM for Urgent(type the cost): ", service_fee);
        scanf("%f", &service_fee);
        break;

      default:
        printf("Invalid option");
    }

    printf("\n\nPayment: ", payment_made);
    scanf("%f", &payment_made);

    if (payment_made > service_fee) {
        changes = payment_made - service_fee;
        printf("\nHere is your changes :%.2f\n", changes);
    }
    fclose(Welcome);
}

void Viewing_Store() {
    FILE *view;
    view = fopen("visitdetails.txt", "r");

    printf("No |    Service Type                                    | Needed Days | Service Fee | \n");
    printf("                                                                      |Normal|Urgent|\n");
    printf("1. | Remove virus,Malware, or Spyware                   |      2      | 30RM | 50RM |\n");
    printf("2. | Troubleshot and fix computer running slow          |      2      | 40RM | 70RM |\n");
    printf("3. | Laptop Screen Replacement                          |      3      | 330RM| 430RM|\n");
    printf("4. | Laptop Keyboard Replacement                        |      2      | 160RM| 200RM|\n");
    printf("5. | Laptop Battery Replacement                         |      1      | 180RM| 210RM|\n");
    printf("6. | Operating System Format and Installation           |      2      | 50RM | 80RM |\n");
    printf("7. | Data Backup and Recovery                           |      2      | 100RM| 150RM|\n");
    printf("8. | Internet Connectivity issues                       |      1      | 50RM | 75RM |\n");

    fclose(view);
}

void change_type() {
    FILE *change;
    char name[20], gender[20], op, option;
    int visit_ID, phone_number, service_needed, change_service, date;
    float service_fee, payment_made, changes, change_service_fee;

    change = fopen("visitdetails.txt", "r");
    printf("\nAre you sure you want to change the service type into(Y/N) : ", op);
    scanf("%s", &op);
    if (op == 'Y') {
        printf("\nWhat service type do you want to change into(1-8)? ", change_service);
        scanf("%d", &change_service);
        switch (change_service) {
          case 1:
            printf("\nThe cost of it will be 30RM for Normal and 50RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 2:
            printf("\nThe cost of it will be 40RM for Normal and 70RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 3:
            printf("\nThe cost of it will be 330RM for Normal and 430RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 4:
            printf("\nThe cost of it will be 160RM for Normal and 200RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 5:
            printf("\nThe cost of it will be 180RM for Normal and 210RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 6:
            printf("\nThe cost of it will be 50RM for Normal and 80RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 7:
            printf("\nThe cost of it will be 100RM for Normal and 150RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          case 8:
            printf("\nThe cost of it will be 50RM for Normal and 75RM for Urgent(type the cost): ", change_service_fee);
            scanf("%f", &change_service_fee);
            break;

          default:
            printf("Invalid option");
        }
    } else
    if (op == 'N') {
        printf("\nThe final price will be : %.2f", service_fee);
    }

    printf("\n\nPayment: ", payment_made);
    scanf("%f", &payment_made);

    if (payment_made > service_fee) {
        changes = payment_made - service_fee;
        printf("\nHere is your changes :%.2f\n", changes);
    } else
    if (payment_made > change_service_fee) {
        changes = payment_made - change_service_fee;
        printf("\nHere is your changes: %.2f\n", changes);
    } else
    if (payment_made == service_fee) {
        changes = payment_made - service_fee;
        printf("\nHere is your changes %f\n", changes);
    } else
    if (payment_made == change_service_fee) {
        changes = payment_made - change_service_fee;
        printf("\nHere is your changes: %f\n", changes);
    } else {
        printf("Error");
    }

    fprintf(change, "\n\nChanging service type into: %d", change_service);
    fprintf(change, "\nThe price of this service type is: %f", change_service_fee);
    fprintf(change,"\nPayment: %.2f", payment_made);
    fclose(change);
}

void any_visit(char anv[]) {
    FILE *anyvisit;
    char name[200], gender[20];
    int visit_ID, phone_number, service_needed, change_service, date, set;
    float service_fee, payment_made, changes, change_service_fee;

    anyvisit = fopen("visitdetails.txt","r");
    while (fscanf(any_visit, "%s %d %d %s %d %d\n", name, visit_ID, date, gender, phone_number, payment_made) != EOF) {
        set = strcmp(date, anv);
        if (set == 0) {
            printf("Visit_ID is %d", visit_ID);
            printf("\nName : %s", name);
            printf("\nGender is %s", gender);
            printf("\nPhone number is %d", phone_number);
            printf("\nPayment : %.2f", payment_made);
        }
    }
    fclose(anyvisit);
}

void search(char cnm[]) {
    FILE *search;
    char name[200], gender[20];
    int visit_ID, phone_number, service_needed, change_service, date, tes;
    float service_fee, payment_made, changes, change_service_fee;

    search = fopen("visitdetails.txt","r");
    while (fscanf(search, "%s %d %d %s %d %d\n", name, visit_ID, date, gender, phone_number, payment_made) != EOF) {
        tes = strcmp(name, cnm);
        if (tes == 0) {
            printf("Visit_ID is %d", visit_ID);
            printf("Date of visit is %d", date);
            printf("\nGender is %s", gender);
            printf("\nPhone number is %d", phone_number);
            printf("\nPayment: %d", date);
        }
    }
    fclose(search);
}

void main() {
    char name[200], gender[20], op, option, ch, cnm[30], anv[30];
    int visit_ID, phone_number, service_needed, change_service, date;
    float service_fee, payment_made, changes, change_service_fee;

    printf("*****Welcome to the Computer center*****\n");
    printf("\nBefore entering the store and have your equipment repair, it is best to view the store\n");
    do {
        printf("\nPress '1' to enter and have your data store");
        printf("\nPress '2' to View the store");
        printf("\nPress '3' to have your equipment being repaired");
        printf("\nPress '4' if you want to change your repair type");
        printf("\nPress '5' if you want to Search");
        printf("\nPress '6' if you want to search payment and unpaid balance by any visit");
        printf("\nPress '0' to exit");
        printf("\nEnter your choice : ");
        scanf("%d", &ch);
        switch(ch) {
          case 1:
            entry();
            break;
          case 2:
            Viewing_Store();
            break;
          case 3:
            Repair();
            break;
          case 4:
            change_type();
            break;
          case 5:
            printf("Enter your name: ");
            scanf("%s", &cnm);
            search(cnm);
            break;
          case 6:
            printf("Enter the date you visit: ");
            scanf("%d", &anv);
            any_visit(anv);
            break;
          case 0:
            exit(0);
          default:
            printf("\nInvalid Entry!!! ");
        }
    } while (ch != 0);
}
```

答:
There are some issues in the posted code:

scanf("%s", &gender); should be scanf("%19s", gender);

why do you read from fpointer in fscanf(fpointer, "%d", service_needed); ?

strcmp(date, anv); is invalid as date is an int.

scanf("%s", &op) is incorrect as op is a single char. You cannot store a string into it. use scanf(" %c", &op) (with an initial space to skip the pending newline).

it is risky to store phone numbers as integers, some may exceed the range of type int and the initial 0 will be lost. Use a string for that.

the contents you write to visitdetails.txt is inconsistent with the way you read from this database. You should just use:

```<code>printf(any_visit, "%s %d %d %s %d %.2f\n", name, visit_ID, date, gender, phone_number, payment_made);
</code>```

main has a return type of int.

There are many more mistakes in the code, compiling with warnings enabled, I get 106 warnings and 1 error.

You should enable all warnings and let the compiler help you avoid type mismatches and similar bugs: use gcc -Wall -Wextra -Werror and fix all these warnings.

Body:
There are some issues in the posted code:

scanf("%s", &gender); should be scanf("%19s", gender);

why do you read from fpointer in fscanf(fpointer, "%d", service_needed); ?

strcmp(date, anv); is invalid as date is an int.

scanf("%s", &op) is incorrect as op is a single char. You cannot store a string into it. use scanf(" %c", &op) (with an initial space to skip the pending newline).

it is risky to store phone numbers as integers, some may exceed the range of type int and the initial 0 will be lost. Use a string for that.

the contents you write to visitdetails.txt is inconsistent with the way you read from this database. You should just use:

printf(any_visit, "%s %d %d %s %d %.2f\n", name, visit_ID, date, gender, phone_number, payment_made);

main has a return type of int.

There are many more mistakes in the code, compiling with warnings enabled, I get 106 warnings and 1 error.

You should enable all warnings and let the compiler help you avoid type mismatches and similar bugs: use gcc -Wall -Wextra -Werror and fix all these warnings.


问:
Bug in Highcharts after exiting the full screen mode
When you open the chart in full screen mode it works as expected: chart is being displayed on the whole screen, but when you exit full screen the original chart stretches to a much bigger height. You can test it here:

https://jsfiddle.net/9b6m438y/

```<code>responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}
</code>```

How to reproduce: Open context menu in upper right corner of chart, select "View in full screen", then exit the full screen mode and pay attention to the height of the original chart.

How to avoid this?

答:
It is a controversial thing if it is a bug or not because different browsers different works in the current full-screen module implementation - you can see the whole discussion here: https://github.com/highcharts/highcharts/issues/13222

As a workaround (suggested under the above link) you can set the container height in the CSS.

Demo: https://jsfiddle.net/9b6m438y/

```<code>#container {
    height: 400px;
}
</code>```

If you have your own opinion about it - feel free to take part in the discussion on the GitHub issue ticket.

Body:
When you open the chart in full screen mode it works as expected: chart is being displayed on the whole screen, but when you exit full screen the original chart stretches to a much bigger height. You can test it here:

https://jsfiddle.net/9b6m438y/

responsive: {
    rules: [{
        condition: {
            maxWidth: 500
        },
        chartOptions: {
            legend: {
                layout: 'horizontal',
                align: 'center',
                verticalAlign: 'bottom'
            }
        }
    }]
}

How to reproduce: Open context menu in upper right corner of chart, select "View in full screen", then exit the full screen mode and pay attention to the height of the original chart.

How to avoid this?

Body:
It is a controversial thing if it is a bug or not because different browsers different works in the current full-screen module implementation - you can see the whole discussion here: https://github.com/highcharts/highcharts/issues/13222

As a workaround (suggested under the above link) you can set the container height in the CSS.

Demo: https://jsfiddle.net/9b6m438y/

#container {
    height: 400px;
}

If you have your own opinion about it - feel free to take part in the discussion on the GitHub issue ticket.


问:
Remove @Override annotation error in Java8
I created the following interface with a single method:

```<code>public interface Greeting {

   public void perform();
}
</code>```

I was trying to pass an instance of the interface to the greet() method.

```<code>public class Greeter {

  public void greet(Greeting greeting){
    greeting.perform();
 }

 public static void main(String[] args) {
    Greeter greeter=new Greeter();
 }
}
</code>```

I created an implementation of Greeting Interface:

```<code>public class HelloWorldGreeting implements Greeting {

 @Override
 public void perform() {
    System.out.println("Hello World");

 }
}
</code>```

I was getting the error(The method perform() of type HelloWorldGreeting must override or implement a supertype method) with a quick fix as "Remove @Override annotation"

I also checked compiler configuration. It's 1.8 only.

Please let me know why is the error coming or help me fix it. Thanks in advance.

答:
right click on the project -> validate

Then select the file want to validate.

It worked for me.

Body:
I created the following interface with a single method:

public interface Greeting {

   public void perform();
}

I was trying to pass an instance of the interface to the greet() method.

public class Greeter {

  public void greet(Greeting greeting){
    greeting.perform();
 }

 public static void main(String[] args) {
    Greeter greeter=new Greeter();
 }
}

I created an implementation of Greeting Interface:

public class HelloWorldGreeting implements Greeting {

 @Override
 public void perform() {
    System.out.println("Hello World");

 }
}

I was getting the error(The method perform() of type HelloWorldGreeting must override or implement a supertype method) with a quick fix as "Remove @Override annotation"

I also checked compiler configuration. It's 1.8 only.

Please let me know why is the error coming or help me fix it. Thanks in advance.


问:
Error when building project with NDK support after updating to Android Studio 4.0 from 3.6
After updating Android Studio to 4.0 project build finishes with error

More than one file was found with OS independent path 'lib/armeabi-v7a/libdlib.so'. If you are using jniLibs and CMake IMPORTED targets, see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake

The link leads to the page with New features in Android Studio Preview which is 4.1

EDIT
Actually you can find information that is linked in Google cache:
Automatic packaging of prebuilt dependencies used by CMake
What is stated there is:

Prior versions of the Android Gradle Plugin required that you explicitly package any prebuilt libraries used by your CMake external native build by using jniLibs. With Android Gradle Plugin 4.0, the above configuration is no longer necessary and will result in a build failure:

But it is not the case for me

Here are build.gradle

```<code>apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"

defaultConfig {
    minSdkVersion 21
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

    externalNativeBuild {
        cmake {
            cFlags "-O3"
            cppFlags "-std=c++11 -frtti -fexceptions -mfpu=neon"
            arguments "-DANDROID_PLATFORM=android-16",
                    "-DANDROID_TOOLCHAIN=clang",
                    "-DANDROID_STL=c++_shared",
                    "-DANDROID_ARM_NEON=TRUE",
                    "-DANDROID_CPP_FEATURES=rtti exceptions"
        }
    }
}

buildTypes {
    debug {}
    stage {
        debuggable true
        minifyEnabled false
    }

    release {
        minifyEnabled false
    }
}

kotlinOptions {
    jvmTarget = "1.8"
}

externalNativeBuild {
    cmake {
        path "src/main/cpp/CMakeLists.txt"
        version "3.10.2"
    }
}

packagingOptions {
    pickFirst "**/libc++_shared.so"
    pickFirst "**/libdlib.so"
}

}

dependencies {
   implementation fileTree(dir: 'libs', include: ['*.jar'])

   implementation 'androidx.annotation:annotation:1.1.0'
   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
</code>```

and CMakeLists.txt

```<code>set(LIB_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)

#
cmake_minimum_required(VERSION 3.4.1)

add_library(dlib SHARED IMPORTED)

# sets the location of the prebuilt dlib .so
set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libdlib.so )

# ------------------------------------------------------------------

add_library( # Sets the name of the library.
        face-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        face-lib.cpp)

target_include_directories(
        face-lib PRIVATE
        ${CMAKE_SOURCE_DIR}/include
)

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

target_link_libraries( # Specifies the target library.
        face-lib

        dlib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})
</code>```

答:
Ok, So I have found the solution, I have added this to the module with my native libraries:

```<code> packagingOptions {
        pickFirst "**/libdlib.so"
    }
</code>```

I don't like it as it, as it fixes the consequences, not the root cause.
If somebody has a better solution please post it here.

Another solution that worked is pointed in @GavinAndre answer
The main point is that if you are using Cmake, then don't store your .so in jniLibs folder.

Move them to another folder for example cmakeLibs.

For example:

```<code>set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../cmakeLibs/${ANDROID_ABI}/libdlib.so )
</code>```

Body:
After updating Android Studio to 4.0 project build finishes with error

More than one file was found with OS independent path 'lib/armeabi-v7a/libdlib.so'. If you are using jniLibs and CMake IMPORTED targets, see https://developer.android.com/studio/preview/features#automatic_packaging_of_prebuilt_dependencies_used_by_cmake

The link leads to the page with New features in Android Studio Preview which is 4.1

EDIT
Actually you can find information that is linked in Google cache:
Automatic packaging of prebuilt dependencies used by CMake
What is stated there is:

Prior versions of the Android Gradle Plugin required that you explicitly package any prebuilt libraries used by your CMake external native build by using jniLibs. With Android Gradle Plugin 4.0, the above configuration is no longer necessary and will result in a build failure:

But it is not the case for me

Here are build.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"

defaultConfig {
    minSdkVersion 21
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

    externalNativeBuild {
        cmake {
            cFlags "-O3"
            cppFlags "-std=c++11 -frtti -fexceptions -mfpu=neon"
            arguments "-DANDROID_PLATFORM=android-16",
                    "-DANDROID_TOOLCHAIN=clang",
                    "-DANDROID_STL=c++_shared",
                    "-DANDROID_ARM_NEON=TRUE",
                    "-DANDROID_CPP_FEATURES=rtti exceptions"
        }
    }
}

buildTypes {
    debug {}
    stage {
        debuggable true
        minifyEnabled false
    }

    release {
        minifyEnabled false
    }
}

kotlinOptions {
    jvmTarget = "1.8"
}

externalNativeBuild {
    cmake {
        path "src/main/cpp/CMakeLists.txt"
        version "3.10.2"
    }
}

packagingOptions {
    pickFirst "**/libc++_shared.so"
    pickFirst "**/libdlib.so"
}

}

dependencies {
   implementation fileTree(dir: 'libs', include: ['*.jar'])

   implementation 'androidx.annotation:annotation:1.1.0'
   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

and CMakeLists.txt

set(LIB_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)

#
cmake_minimum_required(VERSION 3.4.1)

add_library(dlib SHARED IMPORTED)

# sets the location of the prebuilt dlib .so
set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libdlib.so )

# ------------------------------------------------------------------

add_library( # Sets the name of the library.
        face-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        face-lib.cpp)

target_include_directories(
        face-lib PRIVATE
        ${CMAKE_SOURCE_DIR}/include
)

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

target_link_libraries( # Specifies the target library.
        face-lib

        dlib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

Body:
Ok, So I have found the solution, I have added this to the module with my native libraries:

 packagingOptions {
        pickFirst "**/libdlib.so"
    }

I don't like it as it, as it fixes the consequences, not the root cause.
If somebody has a better solution please post it here.

Another solution that worked is pointed in @GavinAndre answer
The main point is that if you are using Cmake, then don't store your .so in jniLibs folder.

Move them to another folder for example cmakeLibs.

For example:

set_target_properties( dlib
        PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../cmakeLibs/${ANDROID_ABI}/libdlib.so )


问:
Print the count of element in a column in table format
Given this dataframe:

```<code>import pandas as pd
df=pd.DataFrame({"Name":["A","A","B"]})
</code>```

I want to print the count of element in Name column in table format as follows:

This is what I am doing right now:

```<code>df['Name'].value_counts().reset_index().rename(columns={'index':'Name','Name':'Count'})
</code>```

Though it works, is there a simpler (shorter way) to achieve the same result?

答:
We can do agg

```<code>df.groupby('Name').agg(Count=('Name','count')).reset_index()
Out[585]:
  Name  Count
0    A      2
1    B      1
</code>```

Body:
Given this dataframe:

import pandas as pd
df=pd.DataFrame({"Name":["A","A","B"]})

I want to print the count of element in Name column in table format as follows:

This is what I am doing right now:

df['Name'].value_counts().reset_index().rename(columns={'index':'Name','Name':'Count'})

Though it works, is there a simpler (shorter way) to achieve the same result?

Body:
We can do agg

df.groupby('Name').agg(Count=('Name','count')).reset_index()
Out[585]:
  Name  Count
0    A      2
1    B      1


问:
initialScrollIndex not working for FlatList react native
I am experiencing an issue with the initialScrollIndex of FlatList - the argument of initialScrollIndex is simply ignored and the first item is shown.

https://snack.expo.io/Bk1mkK0zZ

答:
Just remove the following:

```<code>pagingEnabled = { true }
</code>```

This will fix your example.

Body:
Just remove the following:

pagingEnabled = { true }

This will fix your example.


问:
Java ExceptionHandler whole Class
Is there a way to set a ExceptionHandler for a Class and Exceptionclass?
I have a class like this:

```<code>public class MyServiceClass {

    public void foo() {
        //some Code...
        throw new MyCustomRuntimeException();
        //some more Code...
    }

    public void foo2() {
        //some other Code...
        throw new MyCustomRuntimeException();
        //more other Code...
    }
}
</code>```

Now I would like to define a MyCustomRuntimeException - Handler something like this:

```<code>private void exceptionHandler(MyCustomRuntimeException ex) {
    //some Magic
}
</code>```

Which should be used everytime a MyCustomRuntimeException is thrown in this class. I know I could use try, catch, finally in each method, but is there a Class wide solution? Would like to skip the boilerplate

```<code>try {
...
} catch (MyCustomRuntimeException ex) {
    exceptionHandler(ex);
}
</code>```

Iam using Spring in this application (no Spring Boot), but I found nothing how to use @ExceptionHandler for plain Spring. I tried the following (doesn`t work):

EasyApplication

```<code>import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class EasyApplication {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        FooBar foo = context.getBean(FooBar.class);
        foo.doException();
    }
}
</code>```

FooBar

```<code>import org.springframework.web.bind.annotation.ExceptionHandler;

public class FooBar {

    public void doException() {
        throw new RuntimeException();
    }

     @ExceptionHandler(value = RuntimeException.class)
     public void conflict() {
         System.out.println("Exception handled!");
     }
}
</code>```

MyConfiguration

```<code>import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

    @Bean(name = "FooBar")
    public FooBar fooBar() {
        return new FooBar();
    }
}
</code>```

答:
If you are not using spring-mvc and not in a multi-threaded environment, you would be able to do well with the following.

public class ExceptionHandler implements Thread.UncaughtExceptionHandler {

    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("This is from the uncaught");
    }

}

```

<p>And then add this line in your <code>main</code> method. This works for small applications, and spring has minimal role here.</p>

```Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());

```

If you have a bigger application and needs a more elegant solution - look to introduce aspects (AOP) in to your app.

Edited June 2nd 2020

This is when spring-mvc is used

You can use @ExceptionHandler for this. Spring Tutorial

@ExceptionHandler can handle both class specific and global handlers (via @ControllerAdvice)

The class specific handlers is triggered before global handlers. So best practice is to use RuntimeException and Exception in global handlers, instead of using them in individual classes. Reduces boilerplate further.

Title: Java ExceptionHandler whole Class

Body:
Is there a way to set a ExceptionHandler for a Class and Exceptionclass?
I have a class like this:

public class MyServiceClass {

    public void foo() {
        //some Code...
        throw new MyCustomRuntimeException();
        //some more Code...
    }

    public void foo2() {
        //some other Code...
        throw new MyCustomRuntimeException();
        //more other Code...
    }
}

Now I would like to define a MyCustomRuntimeException - Handler something like this:

private void exceptionHandler(MyCustomRuntimeException ex) {
    //some Magic
}

Which should be used everytime a MyCustomRuntimeException is thrown in this class. I know I could use try, catch, finally in each method, but is there a Class wide solution? Would like to skip the boilerplate

try {
...
} catch (MyCustomRuntimeException ex) {
    exceptionHandler(ex);
}

Iam using Spring in this application (no Spring Boot), but I found nothing how to use @ExceptionHandler for plain Spring. I tried the following (doesn`t work):

EasyApplication

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class EasyApplication {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
        FooBar foo = context.getBean(FooBar.class);
        foo.doException();
    }
}

FooBar

import org.springframework.web.bind.annotation.ExceptionHandler;

public class FooBar {

    public void doException() {
        throw new RuntimeException();
    }

     @ExceptionHandler(value = RuntimeException.class)
     public void conflict() {
         System.out.println("Exception handled!");
     }
}

MyConfiguration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {

    @Bean(name = "FooBar")
    public FooBar fooBar() {
        return new FooBar();
    }
}

Body:
If you are not using spring-mvc and not in a multi-threaded environment, you would be able to do well with the following.

public class ExceptionHandler implements Thread.UncaughtExceptionHandler {

    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("This is from the uncaught");
    }

}

And then add this line in your main method. This works for small applications, and spring has minimal role here.

Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());

If you have a bigger application and needs a more elegant solution - look to introduce aspects (AOP) in to your app.

Edited June 2nd 2020

This is when spring-mvc is used

You can use @ExceptionHandler for this. Spring Tutorial

@ExceptionHandler can handle both class specific and global handlers (via @ControllerAdvice)

The class specific handlers is triggered before global handlers. So best practice is to use RuntimeException and Exception in global handlers, instead of using them in individual classes. Reduces boilerplate further.


问:
Get Full Range Text to String
I'm writing a script that looks through my outgoing emails and searches for frequent stylistic errors I make. It locates them using regex and then highlights them yellow. Code:

```<code>Public Sub highlightBadForm()

    Dim oWordDoc As Object
    Dim oMatches As Object
    Dim oRange As Range
    Dim strText As String
    Dim lngFindFrom As Long
    Dim varMtch As Variant

    Set oWordDoc = Application.ActiveInspector.WordEditor
    strText = LCase(oWordDoc.Range.Text)

    lngFindFrom = InStr(strText, "from: ")
    If lngFindFrom > 0 Then
        strText = Left(strText, lngFindFrom - 1)
    End If

    Set oMatches = extractMatches(strText, getBadStrs)
    If Not oMatches Is Nothing Then
        For Each varMtch In oMatches
                Set oRange = oWordDoc.Range(varMtch.firstindex, varMtch.firstindex + varMtch.Length)
                oRange.HighlightColorIndex = wdYellow
        Next varMtch
    End If

    Set oRange = Nothing
    Set oWordDoc = Nothing
    Set oMatches = Nothing
End Sub
</code>```

extractMatches is a private function implementing VBA's RegEx engine. getBadStrs returns the regular expression containing the errors.

It all works unless I've embedded hyperlinks in my email. If so, oWordDoc.Range.Text returns only the anchor text of the links, not the links (and any other characters Word pads the hyperlinks with - I don't know what they might be). As a result, varMtch.firstindex is correct for strText but not oRange so the text it highlights is offset by several characters.

I tried to assemble the full oRange text by looping through the hyperlinks in oRange and adding the link text to the string assuming it would be included in oRange. Something like:

```<code>Dim lngEndLnk as Long
Set oRange = oWordDoc.Range

For Each varMtch In oRange.Hyperlinks
    strText = strText & oWordDoc.Range(lngEndLnk, varMtch.Range.Start)
    strText = strText & varMtch.TextToDisplay & varMtch.Name
    lngEndLnk = varMtch.Range.End
Next varMtch

If lngEndLnk = 0 Then
    strText = oRange.text
Else
    strText = strText & oWordDoc.Range(lngEndLnk, oWordDoc.Range.End)
End If
</code>```

That reduced the offset, but there still is one. Also, if I were to include a linked image in the email, the .Anchor property of varMtch fails so I'd have to come up with another workaround.

Is there a more straightforward way to get a String containing all the characters of the Range object so the regex indices line up?

答:
The key to this seems to be that when you iterate through a Range looking at each "position" in the range, e.g. via something like

```<code>With ActiveDocument.Range
  For i = 0 to .End - 1
    Debug.Print i,Ascw(.Range(i,i+1).Text)
  Next
End With
</code>```

The Range does contain all the characters in the code of a field such as  HYPERLINK field, and all the characters in its result (which might be displayed or it might be hidden text). But in some cases a Range may contain additional characters which are never displayed. For example, if you have a field code such as { SET x 123 } then the Range contains what are in effect the field braces and the code " SET X 123 ", but before the field end brace it also contains a marker followed by the value "123". But the SET field does not display its result.

That makes it difficult to construct a "find" string that's the same length as the Range.

But Range.Text is the same text as the concatenation of all the characters in Range.Characters, and each Character in that Collection is a Range that contains the .Start position

So that lets us get the .Start and .End as the following example shows.

This assumes you are working with the ActiveDocument in Word, and have some text, a HYPERLINK field (say), and possibly other fields, with the text "test1" in various places.

I haven't done much testing so it may still need tweaking.

```<code>Sub HighlightFinds()
Dim match As VBScript_RegExp_55.match
Dim matches As VBScript_RegExp_55.MatchCollection
Dim rng1 As Word.Range
Dim rng2 As Word.Range
Set rng1 = ActiveDocument.Content
Set rng2 = ActiveDocument.Content ' or rng1.Duplicate

' When you do this, rng1.Text returns the text of the field *codes* but
' not the field *results*, and so does rng1.Characters
'rng1.TextRetrievalMode.IncludeFieldCodes = True
' when you do this, it returns the *results* but not the *codes*
rng1.TextRetrievalMode.IncludeFieldCodes = False

' You could do both, one after the other, to try to get all the matches

' You might also need to set .TextRetrievalMode.IncludeHiddenText

With New VBScript_RegExp_55.RegExp
  .Pattern = "test1"
  .Global = True
  Set matches = .Execute(rng1.Text)
End With
For Each match In matches
  rng2.SetRange rng1.Characters(match.FirstIndex + 1).Start, rng1.Characters(match.FirstIndex + 1 + match.Length).End
  rng2.HighlightColorIndex = wdYellow
Next
Set matches = Nothing
Set rng2 = Nothing
Set rng1 = Nothing
End Sub
</code>```

Title: Get Full Range Text to String

Body:
I'm writing a script that looks through my outgoing emails and searches for frequent stylistic errors I make. It locates them using regex and then highlights them yellow. Code:

Public Sub highlightBadForm()

    Dim oWordDoc As Object
    Dim oMatches As Object
    Dim oRange As Range
    Dim strText As String
    Dim lngFindFrom As Long
    Dim varMtch As Variant

    Set oWordDoc = Application.ActiveInspector.WordEditor
    strText = LCase(oWordDoc.Range.Text)

    lngFindFrom = InStr(strText, "from: ")
    If lngFindFrom > 0 Then
        strText = Left(strText, lngFindFrom - 1)
    End If

    Set oMatches = extractMatches(strText, getBadStrs)
    If Not oMatches Is Nothing Then
        For Each varMtch In oMatches
                Set oRange = oWordDoc.Range(varMtch.firstindex, varMtch.firstindex + varMtch.Length)
                oRange.HighlightColorIndex = wdYellow
        Next varMtch
    End If

    Set oRange = Nothing
    Set oWordDoc = Nothing
    Set oMatches = Nothing
End Sub

extractMatches is a private function implementing VBA's RegEx engine. getBadStrs returns the regular expression containing the errors.

It all works unless I've embedded hyperlinks in my email. If so, oWordDoc.Range.Text returns only the anchor text of the links, not the links (and any other characters Word pads the hyperlinks with - I don't know what they might be). As a result, varMtch.firstindex is correct for strText but not oRange so the text it highlights is offset by several characters.

I tried to assemble the full oRange text by looping through the hyperlinks in oRange and adding the link text to the string assuming it would be included in oRange. Something like:

Dim lngEndLnk as Long
Set oRange = oWordDoc.Range

For Each varMtch In oRange.Hyperlinks
    strText = strText & oWordDoc.Range(lngEndLnk, varMtch.Range.Start)
    strText = strText & varMtch.TextToDisplay & varMtch.Name
    lngEndLnk = varMtch.Range.End
Next varMtch

If lngEndLnk = 0 Then
    strText = oRange.text
Else
    strText = strText & oWordDoc.Range(lngEndLnk, oWordDoc.Range.End)
End If

That reduced the offset, but there still is one. Also, if I were to include a linked image in the email, the .Anchor property of varMtch fails so I'd have to come up with another workaround.

Is there a more straightforward way to get a String containing all the characters of the Range object so the regex indices line up?

Body:
The key to this seems to be that when you iterate through a Range looking at each "position" in the range, e.g. via something like

With ActiveDocument.Range
  For i = 0 to .End - 1
    Debug.Print i,Ascw(.Range(i,i+1).Text)
  Next
End With

The Range does contain all the characters in the code of a field such as  HYPERLINK field, and all the characters in its result (which might be displayed or it might be hidden text). But in some cases a Range may contain additional characters which are never displayed. For example, if you have a field code such as { SET x 123 } then the Range contains what are in effect the field braces and the code " SET X 123 ", but before the field end brace it also contains a marker followed by the value "123". But the SET field does not display its result.

That makes it difficult to construct a "find" string that's the same length as the Range.

But Range.Text is the same text as the concatenation of all the characters in Range.Characters, and each Character in that Collection is a Range that contains the .Start position

So that lets us get the .Start and .End as the following example shows.

This assumes you are working with the ActiveDocument in Word, and have some text, a HYPERLINK field (say), and possibly other fields, with the text "test1" in various places.

I haven't done much testing so it may still need tweaking.

Sub HighlightFinds()
Dim match As VBScript_RegExp_55.match
Dim matches As VBScript_RegExp_55.MatchCollection
Dim rng1 As Word.Range
Dim rng2 As Word.Range
Set rng1 = ActiveDocument.Content
Set rng2 = ActiveDocument.Content ' or rng1.Duplicate

' When you do this, rng1.Text returns the text of the field *codes* but
' not the field *results*, and so does rng1.Characters
'rng1.TextRetrievalMode.IncludeFieldCodes = True
' when you do this, it returns the *results* but not the *codes*
rng1.TextRetrievalMode.IncludeFieldCodes = False

' You could do both, one after the other, to try to get all the matches

' You might also need to set .TextRetrievalMode.IncludeHiddenText

With New VBScript_RegExp_55.RegExp
  .Pattern = "test1"
  .Global = True
  Set matches = .Execute(rng1.Text)
End With
For Each match In matches
  rng2.SetRange rng1.Characters(match.FirstIndex + 1).Start, rng1.Characters(match.FirstIndex + 1 + match.Length).End
  rng2.HighlightColorIndex = wdYellow
Next
Set matches = Nothing
Set rng2 = Nothing
Set rng1 = Nothing
End Sub


问:
Parsing date in JavaScript
When i enter the date and submit, the format of my date is \/06\/12\/1967 and i need in the below format to send my JSON.

The Format Needed With the Slashes to be sent.

```<code>/Date(1306348200000)/
</code>```

答:
Your date is pre 1970, so you should be able to take advantage of the negative number to represent dates before that.

```<code>var str = '\/06\/12\/1967',

    date = new Date(str);

str = '/Date(' + +date + ')/';
</code>```

jsFiddle.

If you need it in seconds as opposed to milliseconds, divide by 1000.

If your date is in the European format (the current date is ambiguous, it could be in either)...

```<code>var str = '\/06\/12\/1967',

    tokens = str.split('/');

str = [tokens[2], tokens[1], tokens[3]].join('/')

var date = new Date(str);

str = '/Date(' + +date + ')/';
</code>```

jsFiddle.

Title: Parsing date in JavaScript

Body:
When i enter the date and submit, the format of my date is \/06\/12\/1967 and i need in the below format to send my JSON.

The Format Needed With the Slashes to be sent.

/Date(1306348200000)/

Body:
Your date is pre 1970, so you should be able to take advantage of the negative number to represent dates before that.

var str = '\/06\/12\/1967',

    date = new Date(str);

str = '/Date(' + +date + ')/';

jsFiddle.

If you need it in seconds as opposed to milliseconds, divide by 1000.

If your date is in the European format (the current date is ambiguous, it could be in either)...

var str = '\/06\/12\/1967',

    tokens = str.split('/');

str = [tokens[2], tokens[1], tokens[3]].join('/')

var date = new Date(str);

str = '/Date(' + +date + ')/';

jsFiddle.