问:
libGoogleAnalytics.a linking problems with iPhone iOS4 Simulator
I recently upgraded to the iOS4 SDK and my app no longer compiles for the simulator, but does compile for the device.

This is due to the 3rd party library libGoogleAnalytics.a. The solution seems to be for google to release a new static library complied with the new SDK, unfortunately there is no word of any release date, and due to the new SDK licensing, they may never release a new library.

http://www.google.com/support/forum/p/Google+Analytics/thread?tid=0e35876711dc99b1&hl=en

I am getting the following compile errors:

```<code>Undefined symbols:
  ".objc_class_name_NSObject", referenced from:
      .objc_class_name_GANTCPSocket in libGoogleAnalytics.a(GANTCPSocket.o)
      .objc_class_name_GTMLogger in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogBasicFormatter in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogLevelFilter in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogNoFilter in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogASLWriter in libGoogleAnalytics.a(GTMLogger+ASL.o)
      .objc_class_name_GTMLoggerASLClient in libGoogleAnalytics.a(GTMLogger+ASL.o)
      .objc_class_name_GANDataDispatcher in libGoogleAnalytics.a(GANDataDispatcher.o)
      .objc_class_name_GANHTTPResponseParser in libGoogleAnalytics.a(GANHTTPResponseParser.o)
      .objc_class_name_GANEvent in libGoogleAnalytics.a(GANEvent.o)
      .objc_class_name_GTMLoggerRingBufferWriter in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      .objc_class_name_GANTracker in libGoogleAnalytics.a(GANTracker.o)
      .objc_class_name_GANPersistentEventStore in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSFileManager", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSFileManager in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSString", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSString in libGoogleAnalytics.a(GTMLogger.o)
      literal-pointer@__OBJC@__cls_refs@NSString in libGoogleAnalytics.a(GANTracker.o)
      literal-pointer@__OBJC@__cls_refs@NSString in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSError", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSError in libGoogleAnalytics.a(GANTracker.o)
      literal-pointer@__OBJC@__cls_refs@NSError in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSFileHandle", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSFileHandle in libGoogleAnalytics.a(GTMLogger.o)
  ".objc_class_name_NSMutableString", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSMutableString in libGoogleAnalytics.a(GANDataDispatcher.o)
  ".objc_class_name_NSTimer", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSTimer in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSMutableArray", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSMutableArray in libGoogleAnalytics.a(GANDataDispatcher.o)
      literal-pointer@__OBJC@__cls_refs@NSMutableArray in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_UIScreen", referenced from:
      literal-pointer@__OBJC@__cls_refs@UIScreen in libGoogleAnalytics.a(GANDataDispatcher.o)
  ".objc_class_name_NSProcessInfo", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSProcessInfo in libGoogleAnalytics.a(GTMLogger.o)
  "_objc_exception_extract", referenced from:
      +[GTMLogger sharedLogger] in libGoogleAnalytics.a(GTMLogger.o)
      +[GTMLogger setSharedLogger:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setWriter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFormatter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFilter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSFileHandle(GTMFileHandleLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSArray(GTMArrayCompositeLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogStandardFormatter stringForFunc:withFormat:valist:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLoggerRingBufferWriter count] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter droppedLogCount] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter reset] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter dumpContents] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter logMessage:level:] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      +[GANTracker sharedTracker] in libGoogleAnalytics.a(GANTracker.o)
      +[GANTracker allocWithZone:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker startTrackerWithAccountID:dispatchPeriod:delegate:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackPageview:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackEvent:action:label:value:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker stopTracker] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker dispatch] in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSDate", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSDate in libGoogleAnalytics.a(GTMLogger.o)
      literal-pointer@__OBJC@__cls_refs@NSDate in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_UIDevice", referenced from:
      literal-pointer@__OBJC@__cls_refs@UIDevice in libGoogleAnalytics.a(GANDataDispatcher.o)
  "_objc_exception_try_exit", referenced from:
      +[GTMLogger sharedLogger] in libGoogleAnalytics.a(GTMLogger.o)
      +[GTMLogger setSharedLogger:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setWriter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFormatter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFilter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSFileHandle(GTMFileHandleLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSArray(GTMArrayCompositeLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogStandardFormatter stringForFunc:withFormat:valist:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLoggerRingBufferWriter count] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter droppedLogCount] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter reset] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter dumpContents] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter logMessage:level:] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      +[GANTracker sharedTracker] in libGoogleAnalytics.a(GANTracker.o)
      +[GANTracker allocWithZone:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker startTrackerWithAccountID:dispatchPeriod:delegate:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackPageview:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackEvent:action:label:value:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker stopTracker] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker dispatch] in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSDateFormatter", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSDateFormatter in libGoogleAnalytics.a(GTMLogger.o)
  "_objc_exception_try_enter", referenced from:
      +[GTMLogger sharedLogger] in libGoogleAnalytics.a(GTMLogger.o)
      +[GTMLogger setSharedLogger:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setWriter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFormatter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFilter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSFileHandle(GTMFileHandleLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSArray(GTMArrayCompositeLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogStandardFormatter stringForFunc:withFormat:valist:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLoggerRingBufferWriter count] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter droppedLogCount] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter reset] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter dumpContents] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter logMessage:level:] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      +[GANTracker sharedTracker] in libGoogleAnalytics.a(GANTracker.o)
      +[GANTracker allocWithZone:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker startTrackerWithAccountID:dispatchPeriod:delegate:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackPageview:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackEvent:action:label:value:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker stopTracker] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker dispatch] in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSUserDefaults", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSUserDefaults in libGoogleAnalytics.a(GTMLogger.o)
  ".objc_class_name_NSThread", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSThread in libGoogleAnalytics.a(GTMLogger+ASL.o)
  ".objc_class_name_NSBundle", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSBundle in libGoogleAnalytics.a(GANDataDispatcher.o)
  ".objc_class_name_NSAssertionHandler", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSAssertionHandler in libGoogleAnalytics.a(GANTracker.o)
      literal-pointer@__OBJC@__cls_refs@NSAssertionHandler in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSLocale", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSLocale in libGoogleAnalytics.a(GANDataDispatcher.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
</code>```

One suggestion on the google forum is to create a dummy implementation of the GANTracker class for use in the simulator. ie to create a file GANTracker_stub.m:

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

#if TARGET_IPHONE_SIMULATOR

@implementation GANTracker

+ (GANTracker *)sharedTracker
{
    return [[[GANTracker alloc] init] autorelease];
}

- (void)startTrackerWithAccountID:(NSString *)accountID
               dispatchPeriod:(NSInteger)dispatchPeriod
                     delegate:(id<GANTrackerDelegate>)delegate
{
}

- (void)stopTracker
{
}

- (BOOL)trackPageview:(NSString *)pageURL
        withError:(NSError **)error
{
    return YES;
}

- (BOOL)trackEvent:(NSString *)category
        action:(NSString *)action
         label:(NSString *)label
         value:(NSInteger)value
     withError:(NSError **)error
{
    return YES;
}

- (BOOL)dispatch
{
    return YES;
}

@end
#endif
</code>```

This however is not working for me, is there something I'm missing?

答:
Using Google Analytics for iOS 0.8 SDK would resolve this problem. I just tried today.

Download it from: http://code.google.com/mobile/analytics/download.html

Body:
I recently upgraded to the iOS4 SDK and my app no longer compiles for the simulator, but does compile for the device.

This is due to the 3rd party library libGoogleAnalytics.a. The solution seems to be for google to release a new static library complied with the new SDK, unfortunately there is no word of any release date, and due to the new SDK licensing, they may never release a new library.

http://www.google.com/support/forum/p/Google+Analytics/thread?tid=0e35876711dc99b1&hl=en

I am getting the following compile errors:

Undefined symbols:
  ".objc_class_name_NSObject", referenced from:
      .objc_class_name_GANTCPSocket in libGoogleAnalytics.a(GANTCPSocket.o)
      .objc_class_name_GTMLogger in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogBasicFormatter in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogLevelFilter in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogNoFilter in libGoogleAnalytics.a(GTMLogger.o)
      .objc_class_name_GTMLogASLWriter in libGoogleAnalytics.a(GTMLogger+ASL.o)
      .objc_class_name_GTMLoggerASLClient in libGoogleAnalytics.a(GTMLogger+ASL.o)
      .objc_class_name_GANDataDispatcher in libGoogleAnalytics.a(GANDataDispatcher.o)
      .objc_class_name_GANHTTPResponseParser in libGoogleAnalytics.a(GANHTTPResponseParser.o)
      .objc_class_name_GANEvent in libGoogleAnalytics.a(GANEvent.o)
      .objc_class_name_GTMLoggerRingBufferWriter in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      .objc_class_name_GANTracker in libGoogleAnalytics.a(GANTracker.o)
      .objc_class_name_GANPersistentEventStore in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSFileManager", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSFileManager in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSString", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSString in libGoogleAnalytics.a(GTMLogger.o)
      literal-pointer@__OBJC@__cls_refs@NSString in libGoogleAnalytics.a(GANTracker.o)
      literal-pointer@__OBJC@__cls_refs@NSString in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSError", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSError in libGoogleAnalytics.a(GANTracker.o)
      literal-pointer@__OBJC@__cls_refs@NSError in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSFileHandle", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSFileHandle in libGoogleAnalytics.a(GTMLogger.o)
  ".objc_class_name_NSMutableString", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSMutableString in libGoogleAnalytics.a(GANDataDispatcher.o)
  ".objc_class_name_NSTimer", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSTimer in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSMutableArray", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSMutableArray in libGoogleAnalytics.a(GANDataDispatcher.o)
      literal-pointer@__OBJC@__cls_refs@NSMutableArray in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_UIScreen", referenced from:
      literal-pointer@__OBJC@__cls_refs@UIScreen in libGoogleAnalytics.a(GANDataDispatcher.o)
  ".objc_class_name_NSProcessInfo", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSProcessInfo in libGoogleAnalytics.a(GTMLogger.o)
  "_objc_exception_extract", referenced from:
      +[GTMLogger sharedLogger] in libGoogleAnalytics.a(GTMLogger.o)
      +[GTMLogger setSharedLogger:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setWriter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFormatter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFilter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSFileHandle(GTMFileHandleLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSArray(GTMArrayCompositeLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogStandardFormatter stringForFunc:withFormat:valist:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLoggerRingBufferWriter count] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter droppedLogCount] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter reset] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter dumpContents] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter logMessage:level:] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      +[GANTracker sharedTracker] in libGoogleAnalytics.a(GANTracker.o)
      +[GANTracker allocWithZone:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker startTrackerWithAccountID:dispatchPeriod:delegate:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackPageview:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackEvent:action:label:value:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker stopTracker] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker dispatch] in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSDate", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSDate in libGoogleAnalytics.a(GTMLogger.o)
      literal-pointer@__OBJC@__cls_refs@NSDate in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_UIDevice", referenced from:
      literal-pointer@__OBJC@__cls_refs@UIDevice in libGoogleAnalytics.a(GANDataDispatcher.o)
  "_objc_exception_try_exit", referenced from:
      +[GTMLogger sharedLogger] in libGoogleAnalytics.a(GTMLogger.o)
      +[GTMLogger setSharedLogger:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setWriter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFormatter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFilter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSFileHandle(GTMFileHandleLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSArray(GTMArrayCompositeLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogStandardFormatter stringForFunc:withFormat:valist:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLoggerRingBufferWriter count] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter droppedLogCount] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter reset] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter dumpContents] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter logMessage:level:] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      +[GANTracker sharedTracker] in libGoogleAnalytics.a(GANTracker.o)
      +[GANTracker allocWithZone:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker startTrackerWithAccountID:dispatchPeriod:delegate:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackPageview:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackEvent:action:label:value:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker stopTracker] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker dispatch] in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSDateFormatter", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSDateFormatter in libGoogleAnalytics.a(GTMLogger.o)
  "_objc_exception_try_enter", referenced from:
      +[GTMLogger sharedLogger] in libGoogleAnalytics.a(GTMLogger.o)
      +[GTMLogger setSharedLogger:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setWriter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFormatter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogger setFilter:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSFileHandle(GTMFileHandleLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[NSArray(GTMArrayCompositeLogWriter) logMessage:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLogStandardFormatter stringForFunc:withFormat:valist:level:] in libGoogleAnalytics.a(GTMLogger.o)
      -[GTMLoggerRingBufferWriter count] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter droppedLogCount] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter reset] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter dumpContents] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      -[GTMLoggerRingBufferWriter logMessage:level:] in libGoogleAnalytics.a(GTMLoggerRingBufferWriter.o)
      +[GANTracker sharedTracker] in libGoogleAnalytics.a(GANTracker.o)
      +[GANTracker allocWithZone:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker startTrackerWithAccountID:dispatchPeriod:delegate:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackPageview:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker trackEvent:action:label:value:withError:] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker stopTracker] in libGoogleAnalytics.a(GANTracker.o)
      -[GANTracker dispatch] in libGoogleAnalytics.a(GANTracker.o)
  ".objc_class_name_NSUserDefaults", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSUserDefaults in libGoogleAnalytics.a(GTMLogger.o)
  ".objc_class_name_NSThread", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSThread in libGoogleAnalytics.a(GTMLogger+ASL.o)
  ".objc_class_name_NSBundle", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSBundle in libGoogleAnalytics.a(GANDataDispatcher.o)
  ".objc_class_name_NSAssertionHandler", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSAssertionHandler in libGoogleAnalytics.a(GANTracker.o)
      literal-pointer@__OBJC@__cls_refs@NSAssertionHandler in libGoogleAnalytics.a(GANPersistentEventStore.o)
  ".objc_class_name_NSLocale", referenced from:
      literal-pointer@__OBJC@__cls_refs@NSLocale in libGoogleAnalytics.a(GANDataDispatcher.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status

One suggestion on the google forum is to create a dummy implementation of the GANTracker class for use in the simulator. ie to create a file GANTracker_stub.m:

#import "GANTracker.h"

#if TARGET_IPHONE_SIMULATOR

@implementation GANTracker

+ (GANTracker *)sharedTracker
{
    return [[[GANTracker alloc] init] autorelease];
}

- (void)startTrackerWithAccountID:(NSString *)accountID
               dispatchPeriod:(NSInteger)dispatchPeriod
                     delegate:(id<GANTrackerDelegate>)delegate
{
}

- (void)stopTracker
{
}

- (BOOL)trackPageview:(NSString *)pageURL
        withError:(NSError **)error
{
    return YES;
}

- (BOOL)trackEvent:(NSString *)category
        action:(NSString *)action
         label:(NSString *)label
         value:(NSInteger)value
     withError:(NSError **)error
{
    return YES;
}

- (BOOL)dispatch
{
    return YES;
}

@end
#endif

This however is not working for me, is there something I'm missing?


来源: stackexchange

问:
Error during inference: Invalid argument: No OpKernel was registered to support Op 'DecodeJpeg' with these attrs
I got this error message when I ran the app. It crash just a few seconds after app launched.</p>

```<code>05-28 09:05:29.791 15453-15472/my.xxxxx.androidtensorflowbirdexample A/native: tensorflow_jni.cc:304 Error during inference: Invalid argument: No OpKernel was registered to support Op 'DecodeJpeg' with these attrs
                                                                                [[Node: DecodeJpeg = DecodeJpeg[acceptable_fraction=1, channels=3, dct_method="", fancy_upscaling=true, ratio=1, try_recover_truncated=false](DecodeJpeg/contents)]]
05-28 09:05:29.791 15453-15472/my.xxxxx.androidtensorflowbirdexample A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 15472 (InferenceThread)

                                                                                [ 05-28 09:05:29.796 15453:15503 E/         ]
                                                                                [android_ws] Format: 5, Width: 1080, Height: 1620

                                                                                [ 05-28 09:05:29.796 15453:15503 E/         ]
                                                                                [android_ws] Format: 5, Width: 1080, Height: 1620
</code>```

答:
You have to convert the output graph to optimized graph or quantized graph.

First, build the appropriate tools for the conversion:

For optimized graph,

```<code>bazel build tensorflow/python/tools:optimize_for_inference
</code>```

For quantized graph,

```<code>bazel build tensorflow/tools/quantization:quantize_graph
</code>```

And then, convert you retrained graph to the desired format:

retrained -> optimized

```<code>tensorflow/bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=train/output/flower_photos/retrained_graph.pb \
--output=train/output/flower_photos/optimized_graph.pb \
--input_names=Mul \
--output_names=final_result
</code>```

optimized -> quantized

```<code>bazel-bin/tensorflow/tools/quantization/quantize_graph \
--input=train/output/flower_photos/optimized_graph.pb \
--output=train/output/flower_photos/rounded_graph.pb \
--output_node_names=final_result \
--mode=weights_rounded
</code>```

you have to use appropriate graph name you have and input/output node names can be different if you created the graph from scratch

For more information, please refer to:
https://petewarden.com/2016/09/27/tensorflow-for-mobile-poets/
(it's a little bit outdated, but you can get great overview of the android implementation)

ContentLicense: CC BY-SA 4.0

Body:
I got this error message when I ran the app. It crash just a few seconds after app launched.

05-28 09:05:29.791 15453-15472/my.xxxxx.androidtensorflowbirdexample A/native: tensorflow_jni.cc:304 Error during inference: Invalid argument: No OpKernel was registered to support Op 'DecodeJpeg' with these attrs
                                                                                [[Node: DecodeJpeg = DecodeJpeg[acceptable_fraction=1, channels=3, dct_method="", fancy_upscaling=true, ratio=1, try_recover_truncated=false](DecodeJpeg/contents)]]
05-28 09:05:29.791 15453-15472/my.xxxxx.androidtensorflowbirdexample A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 15472 (InferenceThread)

                                                                                [ 05-28 09:05:29.796 15453:15503 E/         ]
                                                                                [android_ws] Format: 5, Width: 1080, Height: 1620

                                                                                [ 05-28 09:05:29.796 15453:15503 E/         ]
                                                                                [android_ws] Format: 5, Width: 1080, Height: 1620

Body:
You have to convert the output graph to optimized graph or quantized graph.

First, build the appropriate tools for the conversion:

For optimized graph,

bazel build tensorflow/python/tools:optimize_for_inference

For quantized graph,

bazel build tensorflow/tools/quantization:quantize_graph

And then, convert you retrained graph to the desired format:

retrained -> optimized

tensorflow/bazel-bin/tensorflow/python/tools/optimize_for_inference \
--input=train/output/flower_photos/retrained_graph.pb \
--output=train/output/flower_photos/optimized_graph.pb \
--input_names=Mul \
--output_names=final_result

optimized -> quantized

bazel-bin/tensorflow/tools/quantization/quantize_graph \
--input=train/output/flower_photos/optimized_graph.pb \
--output=train/output/flower_photos/rounded_graph.pb \
--output_node_names=final_result \
--mode=weights_rounded

you have to use appropriate graph name you have and input/output node names can be different if you created the graph from scratch

For more information, please refer to:
https://petewarden.com/2016/09/27/tensorflow-for-mobile-poets/
(it's a little bit outdated, but you can get great overview of the android implementation)

ContentLicense: CC BY-SA 3.0


问:
Android Studio 3.0 Canary 2: attribute 'android:versionCode' not found
I've updated Android Studio to the latest canary build and now I can't run my app.

Every time when I try to build the project I get the following error:

```<code>Error:F:\...\**app_name**\app\build\intermediates\instant-run-support\debug\slice_0\AndroidManifest.xml:2 attribute 'android:versionCode' not found
</code>```

I tried to manually open the file and the attribute is clearly there:

```<code><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="****"
      android:versionCode="1"
      android:versionName="1.0"
      split="lib_slice_0_apk">
</manifest>
</code>```

I've tried to clean the project, invalidate cache, restart android studio but nothing helped.

This is my build.gradle (app) file:

```<code>apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "****"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:design:25.3.1'
    compile 'com.android.support:cardview-v7:25.3.1'
    compile 'com.squareup.picasso:picasso:2.5.2'
}
</code>```

答:
Clean and rebuild the project
and restart android studio.
It will work.</p>

Body:
I've updated Android Studio to the latest canary build and now I can't run my app.

Every time when I try to build the project I get the following error:

Error:F:\...\**app_name**\app\build\intermediates\instant-run-support\debug\slice_0\AndroidManifest.xml:2 attribute 'android:versionCode' not found

I tried to manually open the file and the attribute is clearly there:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="****"
      android:versionCode="1"
      android:versionName="1.0"
      split="lib_slice_0_apk">
</manifest>

I've tried to clean the project, invalidate cache, restart android studio but nothing helped.

This is my build.gradle (app) file:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "****"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:design:25.3.1'
    compile 'com.android.support:cardview-v7:25.3.1'
    compile 'com.squareup.picasso:picasso:2.5.2'
}


问:
Cannot require cloneDeep from lodash
var cloneDeep = require('lodash/lang/cloneDeep');

I was under the impression that you could require specific functions from lodash to increase performance but I just get an error saying cannot find module lodash/lang/cloneDeep. I looked at the lodash docs and I believe this is the correct path to the function. What am I doing wrong?

答: Lodash removed category names from module paths since 4.0 (Changelog). What you want is require('lodash/cloneDeep')

Title: Cannot require cloneDeep from lodash


问:
Regex to match any url in img tag
I need a regular expression that can match any url in img src tag

URL can vary from "/images/temp.jpg" or "temp1.jpg" or even "http://www.example.com/temp.jpg?i=123" or anything

I have written following code:

```<code>preg_match_all('/(href|src)\s*=\s*"([^\s]+\/\/[^\/]+.\/[^\s]+\.(jpg|jpeg|png|gif|bmp))/ixu'
</code>```

but it's not matching many urls including those with query string like ?i=12345

Anyone have idea how to achieve this?

Thanks

答:
Search first, asked and answered hundreds of times over the years:

regular expression: Find url from anchor tag

Just replace <a with <img and href with src

Title: Regex to match any url in img tag

Body:
I need a regular expression that can match any url in img src tag

URL can vary from "/images/temp.jpg" or "temp1.jpg" or even "http://www.example.com/temp.jpg?i=123" or anything

I have written following code:

preg_match_all('/(href|src)\s*=\s*"([^\s]+\/\/[^\/]+.\/[^\s]+\.(jpg|jpeg|png|gif|bmp))/ixu'

but it's not matching many urls including those with query string like ?i=12345

Anyone have idea how to achieve this?

Thanks

ContentLicense: CC BY-SA 2.5


问:
androidplot 1.4.3 redraw run-time analysis with JNI getY (idx) access
i did evaluate the run-time performance of a 6 XYSeries plot setup (500 X axis samples) on a nexus 7 2013 with simple synthesized sine waves in the getY (idx) functs and compared it to a JNI getY (idx) based setup where the JNI C++ code simply fetched the data from a buffer within the JNI capsule

here is a simplified setup for the synthesized sine wave generation (example shows one XYSeries)

```<code>public static int  DatCnt = 0 ;
       static long DatSav ;

@Override
public double GetY (int idx) // being called by super.getY (idx), which implements XYSeries
{
  long t0 = 0 ;

  if (DatCnt >    0) { DatCnt-- ; t0 = System.nanoTime () ; }
  if (DatCnt == 499)   DatSav   = t0 ;

  double dat = Sin (idx) * 45 + 50 ;

//if (DatCnt >    0 &&
//    DatCnt <   10) {
//  Log.i ("com.efiLabs.PlotXYtst", String.format ("dat0 %6d %d", (System.nanoTime () - t0) / 1000, DatCnt)) ;
//}
  if (DatCnt ==   1) {                                                                   ActPlotNew0.Tsum += t0 - DatSav ;
    Log.i ("com.efiLabs.PlotXYtst", String.format ("dat0 %6d %6d", (t0 - DatSav) / 1000, ActPlotNew0.Tsum / 1000)) ;
  }
  return dat ;
//return Sin (idx) * 45 + 50 ;
}
</code>```

and this is the android monitor output

```<code>06-04 16:14:40.707 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onDown x_1493 y_523
06-04 16:14:40.797 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_23
06-04 16:14:40.797 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 233989457389
06-04 16:14:40.861 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0  33874  33874
06-04 16:14:40.901 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1  26428  60302
06-04 16:14:40.938 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2  24627  84930
06-04 16:14:40.974 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3  25299 110229
06-04 16:14:41.010 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4  24047 134277
06-04 16:14:41.046 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5  25299 159576
06-04 16:14:41.069 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_517
06-04 16:14:41.069 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 272247
06-04 16:14:41.129 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0  24322  24322
06-04 16:14:41.165 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1  24536  48858
06-04 16:14:41.200 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2  24688  73547
06-04 16:14:41.236 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3  24414  97961
06-04 16:14:41.271 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4  23895 121856
06-04 16:14:41.305 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5  23834 145690
06-04 16:14:41.326 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_37
06-04 16:14:41.326 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 256622
06-04 16:14:41.387 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0  23834  23834
06-04 16:14:41.429 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1  30395  54229
06-04 16:14:41.473 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2  28411  82641
06-04 16:14:41.507 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3  23406 106048
06-04 16:14:41.542 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4  23803 129852
06-04 16:14:41.576 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5  24108 153961
</code>```

a vertical scroll will start the loop with the DatUpd () functs being called periodically

```<code>public static long Tstart, Tsum ;

public synchronized void DataUpd ()
{

  LogI (String.format ("sum %d", (System.nanoTime () - Tstart) / 1000)) ;

  DataY_0.DatCnt = 500 ;
  DataY_1.DatCnt = 500 ;
  DataY_2.DatCnt = 500 ;
  DataY_3.DatCnt = 500 ;
  DataY_4.DatCnt = 500 ;
  DataY_5.DatCnt = 500 ;

  Tstart = System.nanoTime () ;
  Tsum   = 0 ;

  Plot.redraw () ;
}
</code>```

the "dat3 25299 110229" shows the exex times for each series (dat0 - dat5), whereas the 1st number is the individual time accumulation from the x-data 0 to 500, and the 2nd is a running time tally ... 25299 us for the dat3 series and 110299 us for dat0 to dat3 and so on ... an average data fetch time per ZYSeries is about 25 ms

the total sum of 272247 us is the time from the 1st DatUpd () call to the next one in the scroll operation ... i didn't have a hook into when the plot redraw process was complete

the total getY (idx) data fetch time for all 6 XYSeries is 159576 us and the total redraw cycle time 272247 us ... 272247 - 159576 = 112671 us

of course i do not have any idea of the percentage of the remaining time (after the fetch time) of 112671 us, which is androidplot time and which is scroll gesture processing

and now to the C++ JNI setup timing

```<code>06-04 17:09:39.783 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onDown x_1620 y_497
06-04 17:09:39.881 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_16
06-04 17:09:39.882 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 25543273
06-04 17:09:39.947 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rdif  36865  36865
06-04 17:09:39.995 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rpm   36956  73822
06-04 17:09:40.032 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: tdif  36224 110046
06-04 17:09:40.085 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext0  42205 152252
06-04 17:09:40.138 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext1  41778 194030
06-04 17:09:40.202 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: raw2  53955 247985
06-04 17:09:40.226 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_724
06-04 17:09:40.226 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 344085
06-04 17:09:40.293 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rdif  36956  36956
06-04 17:09:40.341 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rpm   36651  73608
06-04 17:09:40.377 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: tdif  36315 109924
06-04 17:09:40.429 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext0  40954 150878
06-04 17:09:40.481 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext1  40802 191680
06-04 17:09:40.534 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: raw2  41015 232696
06-04 17:09:40.555 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_4
06-04 17:09:40.555 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 329620
06-04 17:09:40.619 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rdif  36712  36712
06-04 17:09:40.666 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rpm   36499  73211
06-04 17:09:40.702 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: tdif  36163 109375
06-04 17:09:40.779 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext0  63323 172698
06-04 17:09:40.836 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext1  42266 214965
06-04 17:09:40.888 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: raw2  41259 256225
</code>```

comparison :

accumulated fetch time is 247985 us

the sine synthesized data fetches take an average 25 ms / series whereas the C++ JNI data fetches take about 40 ms ... 15 ms longer, an increase of 60 % over the sine wave synthesis example

the percentage of the getY (idx) synthesized sine wave generation time portion is unknown and so is what else is happening inside androidplot from one getY (idx) to the next one

25 ms / 500 x-samples is 50 us, 15 ms / 500 x-samples = 30 us   ... assuming that the sine calculation can't take the majority of the 50 us i would say that a single getY (idx) call processing, not counting the data fetch takes maybe 40 to 45 us ...

the C++ JNI data fetch time of 30 us is not lightning fast, but something i have to live with ... 30 us * 500 * 6 = 90 ms for the whole data fetch only portion ... i could do this 10 times / sec if the redraw wouldn't take any time

i use the FastLineAndPointRenderer.Formatter setup

```<code>public static FastLineAndPointRenderer.Formatter LineFormat (int color, int width, int dash, int spc)
{
  Paint paint = new Paint () ;
  paint.setColor (color) ;
  paint.setStyle (Paint.Style.STROKE) ;
  paint.setAntiAlias (false) ;
  paint.setStrokeWidth (PixelUtils.dpToPix (width)) ;
  paint.setPathEffect (new DashPathEffect (
                       new float [] { PixelUtils.dpToPix (dash), PixelUtils.dpToPix (spc) }, 0)) ;

  FastLineAndPointRenderer.Formatter line = new FastLineAndPointRenderer.Formatter (paint.getColor (), null, null) ;
  line.setLinePaint     (paint) ;
  line.setVertexPaint       (null) ;
  line.setPointLabelFormatter (null) ;

  return line ;
}
</code>```

please, can anyone shine a bit more light onto my setup and comment this paper

is there a way to speed it up and still sick with 500 x-points ... that's what's being used in QT on the desktop setup and it's zippy zippy fast

what can be improved and what additional info should i provide

i hope i do not have made too many typos ;)

答:
did more testing and lowered the x-points from 500 to 50 for the sine synthesized plot and here is the data

```<code>06-04 20:11:16.172 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onDown x_1464 y_562
06-04 20:11:16.407 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_24
06-04 20:11:16.407 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 46652130
06-04 20:11:16.442 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0   2319   2319
06-04 20:11:16.471 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1   2380   4699
06-04 20:11:16.512 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2   2410   7110
06-04 20:11:16.549 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3   2288   9399
06-04 20:11:16.580 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4   2593  11993
06-04 20:11:16.610 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5   2532  14526
06-04 20:11:16.650 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_350
06-04 20:11:16.651 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 243133
06-04 20:11:16.689 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0   2288   2288
06-04 20:11:16.720 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1   2319   4608
06-04 20:11:16.751 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2   2288   6896
06-04 20:11:16.782 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3   2685   9582
06-04 20:11:16.812 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4   2319  11901
06-04 20:11:16.842 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5   2410  14312
06-04 20:11:16.881 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_46
06-04 20:11:16.881 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 230346
06-04 20:11:16.915 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0   2319   2319
06-04 20:11:16.944 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1   2349   4669
06-04 20:11:16.973 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2   2410   7080
06-04 20:11:17.002 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3   2319   9399
06-04 20:11:17.033 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4   2471  11871
06-04 20:11:17.064 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5   2563  14434
06-04 20:11:17.116 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_2
</code>```

yes, the getY (idx) times for 50 x samples compared to 500 are now 2.5 ms compared to 25 ms with 500

but the total time redraw scoll still remains 240 ms ... how come ???

here is my scroll funct inherited from a base class just calling it

```<code>protected boolean OnScroll (MotionEvent evt0, MotionEvent evt1, float dx, float dy)
{
  DataY.Offs += (dx * 50) / (mWidth - mWidth / 12) ; DataUpd () ;
  return true ;
}
</code>```

am i doing something wrong with the scroll handling of the plot ???

the previous timing values with 500 x-data points sort of match, but now ??? what happens in the 243 ms  with the getY (idx) only taking up 14 ms ... why is the scroll refresh frequ not increasing ???

the whole graph scolling is still as jerky as before

Body:
i did evaluate the run-time performance of a 6 XYSeries plot setup (500 X axis samples) on a nexus 7 2013 with simple synthesized sine waves in the getY (idx) functs and compared it to a JNI getY (idx) based setup where the JNI C++ code simply fetched the data from a buffer within the JNI capsule

here is a simplified setup for the synthesized sine wave generation (example shows one XYSeries)

public static int  DatCnt = 0 ;
       static long DatSav ;

@Override
public double GetY (int idx) // being called by super.getY (idx), which implements XYSeries
{
  long t0 = 0 ;

  if (DatCnt >    0) { DatCnt-- ; t0 = System.nanoTime () ; }
  if (DatCnt == 499)   DatSav   = t0 ;

  double dat = Sin (idx) * 45 + 50 ;

//if (DatCnt >    0 &&
//    DatCnt <   10) {
//  Log.i ("com.efiLabs.PlotXYtst", String.format ("dat0 %6d %d", (System.nanoTime () - t0) / 1000, DatCnt)) ;
//}
  if (DatCnt ==   1) {                                                                   ActPlotNew0.Tsum += t0 - DatSav ;
    Log.i ("com.efiLabs.PlotXYtst", String.format ("dat0 %6d %6d", (t0 - DatSav) / 1000, ActPlotNew0.Tsum / 1000)) ;
  }
  return dat ;
//return Sin (idx) * 45 + 50 ;
}

and this is the android monitor output

06-04 16:14:40.707 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onDown x_1493 y_523
06-04 16:14:40.797 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_23
06-04 16:14:40.797 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 233989457389
06-04 16:14:40.861 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0  33874  33874
06-04 16:14:40.901 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1  26428  60302
06-04 16:14:40.938 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2  24627  84930
06-04 16:14:40.974 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3  25299 110229
06-04 16:14:41.010 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4  24047 134277
06-04 16:14:41.046 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5  25299 159576
06-04 16:14:41.069 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_517
06-04 16:14:41.069 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 272247
06-04 16:14:41.129 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0  24322  24322
06-04 16:14:41.165 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1  24536  48858
06-04 16:14:41.200 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2  24688  73547
06-04 16:14:41.236 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3  24414  97961
06-04 16:14:41.271 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4  23895 121856
06-04 16:14:41.305 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5  23834 145690
06-04 16:14:41.326 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_37
06-04 16:14:41.326 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 256622
06-04 16:14:41.387 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0  23834  23834
06-04 16:14:41.429 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1  30395  54229
06-04 16:14:41.473 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2  28411  82641
06-04 16:14:41.507 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3  23406 106048
06-04 16:14:41.542 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4  23803 129852
06-04 16:14:41.576 18061-18061/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5  24108 153961

a vertical scroll will start the loop with the DatUpd () functs being called periodically

public static long Tstart, Tsum ;

public synchronized void DataUpd ()
{

  LogI (String.format ("sum %d", (System.nanoTime () - Tstart) / 1000)) ;

  DataY_0.DatCnt = 500 ;
  DataY_1.DatCnt = 500 ;
  DataY_2.DatCnt = 500 ;
  DataY_3.DatCnt = 500 ;
  DataY_4.DatCnt = 500 ;
  DataY_5.DatCnt = 500 ;

  Tstart = System.nanoTime () ;
  Tsum   = 0 ;

  Plot.redraw () ;
}

the "dat3 25299 110229" shows the exex times for each series (dat0 - dat5), whereas the 1st number is the individual time accumulation from the x-data 0 to 500, and the 2nd is a running time tally ... 25299 us for the dat3 series and 110299 us for dat0 to dat3 and so on ... an average data fetch time per ZYSeries is about 25 ms

the total sum of 272247 us is the time from the 1st DatUpd () call to the next one in the scroll operation ... i didn't have a hook into when the plot redraw process was complete

the total getY (idx) data fetch time for all 6 XYSeries is 159576 us and the total redraw cycle time 272247 us ... 272247 - 159576 = 112671 us

of course i do not have any idea of the percentage of the remaining time (after the fetch time) of 112671 us, which is androidplot time and which is scroll gesture processing

and now to the C++ JNI setup timing

06-04 17:09:39.783 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onDown x_1620 y_497
06-04 17:09:39.881 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_16
06-04 17:09:39.882 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 25543273
06-04 17:09:39.947 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rdif  36865  36865
06-04 17:09:39.995 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rpm   36956  73822
06-04 17:09:40.032 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: tdif  36224 110046
06-04 17:09:40.085 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext0  42205 152252
06-04 17:09:40.138 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext1  41778 194030
06-04 17:09:40.202 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: raw2  53955 247985
06-04 17:09:40.226 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_724
06-04 17:09:40.226 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 344085
06-04 17:09:40.293 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rdif  36956  36956
06-04 17:09:40.341 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rpm   36651  73608
06-04 17:09:40.377 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: tdif  36315 109924
06-04 17:09:40.429 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext0  40954 150878
06-04 17:09:40.481 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext1  40802 191680
06-04 17:09:40.534 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: raw2  41015 232696
06-04 17:09:40.555 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_4
06-04 17:09:40.555 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 329620
06-04 17:09:40.619 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rdif  36712  36712
06-04 17:09:40.666 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: rpm   36499  73211
06-04 17:09:40.702 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: tdif  36163 109375
06-04 17:09:40.779 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext0  63323 172698
06-04 17:09:40.836 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: ext1  42266 214965
06-04 17:09:40.888 4067-4067/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: raw2  41259 256225

comparison :

accumulated fetch time is 247985 us

the sine synthesized data fetches take an average 25 ms / series whereas the C++ JNI data fetches take about 40 ms ... 15 ms longer, an increase of 60 % over the sine wave synthesis example

the percentage of the getY (idx) synthesized sine wave generation time portion is unknown and so is what else is happening inside androidplot from one getY (idx) to the next one

25 ms / 500 x-samples is 50 us, 15 ms / 500 x-samples = 30 us   ... assuming that the sine calculation can't take the majority of the 50 us i would say that a single getY (idx) call processing, not counting the data fetch takes maybe 40 to 45 us ...

the C++ JNI data fetch time of 30 us is not lightning fast, but something i have to live with ... 30 us * 500 * 6 = 90 ms for the whole data fetch only portion ... i could do this 10 times / sec if the redraw wouldn't take any time

i use the FastLineAndPointRenderer.Formatter setup

public static FastLineAndPointRenderer.Formatter LineFormat (int color, int width, int dash, int spc)
{
  Paint paint = new Paint () ;
  paint.setColor (color) ;
  paint.setStyle (Paint.Style.STROKE) ;
  paint.setAntiAlias (false) ;
  paint.setStrokeWidth (PixelUtils.dpToPix (width)) ;
  paint.setPathEffect (new DashPathEffect (
                       new float [] { PixelUtils.dpToPix (dash), PixelUtils.dpToPix (spc) }, 0)) ;

  FastLineAndPointRenderer.Formatter line = new FastLineAndPointRenderer.Formatter (paint.getColor (), null, null) ;
  line.setLinePaint     (paint) ;
  line.setVertexPaint       (null) ;
  line.setPointLabelFormatter (null) ;

  return line ;
}

please, can anyone shine a bit more light onto my setup and comment this paper

is there a way to speed it up and still sick with 500 x-points ... that's what's being used in QT on the desktop setup and it's zippy zippy fast

what can be improved and what additional info should i provide

i hope i do not have made too many typos ;)

Body:
did more testing and lowered the x-points from 500 to 50 for the sine synthesized plot and here is the data

06-04 20:11:16.172 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onDown x_1464 y_562
06-04 20:11:16.407 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_24
06-04 20:11:16.407 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 46652130
06-04 20:11:16.442 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0   2319   2319
06-04 20:11:16.471 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1   2380   4699
06-04 20:11:16.512 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2   2410   7110
06-04 20:11:16.549 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3   2288   9399
06-04 20:11:16.580 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4   2593  11993
06-04 20:11:16.610 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5   2532  14526
06-04 20:11:16.650 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_350
06-04 20:11:16.651 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 243133
06-04 20:11:16.689 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0   2288   2288
06-04 20:11:16.720 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1   2319   4608
06-04 20:11:16.751 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2   2288   6896
06-04 20:11:16.782 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3   2685   9582
06-04 20:11:16.812 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4   2319  11901
06-04 20:11:16.842 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5   2410  14312
06-04 20:11:16.881 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_46
06-04 20:11:16.881 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: sum 230346
06-04 20:11:16.915 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat0   2319   2319
06-04 20:11:16.944 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat1   2349   4669
06-04 20:11:16.973 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat2   2410   7080
06-04 20:11:17.002 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat3   2319   9399
06-04 20:11:17.033 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat4   2471  11871
06-04 20:11:17.064 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: dat5   2563  14434
06-04 20:11:17.116 26868-26868/com.efiLabs.PlotXY2tst I/com.efiLabs.PlotXYtst: onScroll x_2

yes, the getY (idx) times for 50 x samples compared to 500 are now 2.5 ms compared to 25 ms with 500

but the total time redraw scoll still remains 240 ms ... how come ???

here is my scroll funct inherited from a base class just calling it

protected boolean OnScroll (MotionEvent evt0, MotionEvent evt1, float dx, float dy)
{
  DataY.Offs += (dx * 50) / (mWidth - mWidth / 12) ; DataUpd () ;
  return true ;
}

am i doing something wrong with the scroll handling of the plot ???

the previous timing values with 500 x-data points sort of match, but now ??? what happens in the 243 ms  with the getY (idx) only taking up 14 ms ... why is the scroll refresh frequ not increasing ???

the whole graph scolling is still as jerky as before


问:
VBA optimize performance for 3 loops
First I wish to check if the value in in each row of column D of "Sheet1" matches any row of column A of "Accepted". If there is a match, I would like to copy the value in column B of that row of "Sheet1" into column D of "Accepted".

However, as there are 2 possible values in column B of "Sheet1", I would like to split the values into two columns of "Accepted" - Columns D and E. Hence, the next loop, if the value in column D of "Accepted" is not "Restricted", then copy that value into Column E and remove content of Column D.

The code works fine in that it helps me to achieve my goal, however, the process is taking too long, and after some investigation I found out that the delay only occurs with the last loop. I was wondering if I could speed up this process, thanks!

```<code>Dim i As Long
Dim j As Long
Dim k As Long

'to speed up the VBA code
With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
End With

AcceptedLastRow = ActiveWorkbook.Worksheets("Accepted").Range("A" & Rows.Count).End(xlUp).Row
Sheet1LastRow = ActiveWorkbook.Worksheets("Sheet1").Range("D" & Rows.Count).End(xlUp).Row

    For j = 1 To AcceptedLastRow
        For i = 1 To Sheet1LastRow
            If ActiveWorkbook.Worksheets("Sheet1").Cells(i, 4).Value = ActiveWorkbook.Worksheets("Accepted").Cells(j, 1).Value Then
            ActiveWorkbook.Worksheets("Accepted").Cells(j, 4).Value = ActiveWorkbook.Worksheets("Sheet1").Cells(i, 2).Value
            End If
        Next i
    Next j

'to transfer recognised status to the recognised column and to remove from restricted column
'I think this is the section which contributes to the lag/delay
Restrictedlastrow = ActiveWorkbook.Worksheets("Accepted").Range("D" & Rows.Count).End(xlUp).Row
    For k = 9 To Restrictedlastrow
        If ActiveWorkbook.Sheets("Accepted").Cells(k, 4).Value <> "Restricted" Then
        ActiveWorkbook.Sheets("Accepted").Cells(k, 4).Copy ActiveWorkbook.Sheets("Accepted").Cells(k, 5)
        ActiveWorkbook.Sheets("Accepted").Cells(k, 4).ClearContents
        End If
    Next k

'to reset settings back to normal
With Application
    .Calculation = xlCalculationAutomatic
    .ScreenUpdating = True
End With
</code>```

答:
Instead of

```<code>ActiveWorkbook.Sheets("Accepted").Cells(k, 4).Copy ActiveWorkbook.Sheets("Accepted").Cells(k, 5)
</code>```

Use

```<code>ActiveWorkbook.Sheets("Accepted").Cells(k, 5) = ActiveWorkbook.Sheets("Accepted").Cells(k, 4)
</code>```

Copy is an expensive operation. Since you seem to be interested only in a value of a cell, assign it directly (like you did in the previous loops).

Title: VBA optimize performance for 3 loops

Body:
First I wish to check if the value in in each row of column D of "Sheet1" matches any row of column A of "Accepted". If there is a match, I would like to copy the value in column B of that row of "Sheet1" into column D of "Accepted".

However, as there are 2 possible values in column B of "Sheet1", I would like to split the values into two columns of "Accepted" - Columns D and E. Hence, the next loop, if the value in column D of "Accepted" is not "Restricted", then copy that value into Column E and remove content of Column D.

The code works fine in that it helps me to achieve my goal, however, the process is taking too long, and after some investigation I found out that the delay only occurs with the last loop. I was wondering if I could speed up this process, thanks!

Dim i As Long
Dim j As Long
Dim k As Long

'to speed up the VBA code
With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
End With

AcceptedLastRow = ActiveWorkbook.Worksheets("Accepted").Range("A" & Rows.Count).End(xlUp).Row
Sheet1LastRow = ActiveWorkbook.Worksheets("Sheet1").Range("D" & Rows.Count).End(xlUp).Row

    For j = 1 To AcceptedLastRow
        For i = 1 To Sheet1LastRow
            If ActiveWorkbook.Worksheets("Sheet1").Cells(i, 4).Value = ActiveWorkbook.Worksheets("Accepted").Cells(j, 1).Value Then
            ActiveWorkbook.Worksheets("Accepted").Cells(j, 4).Value = ActiveWorkbook.Worksheets("Sheet1").Cells(i, 2).Value
            End If
        Next i
    Next j

'to transfer recognised status to the recognised column and to remove from restricted column
'I think this is the section which contributes to the lag/delay
Restrictedlastrow = ActiveWorkbook.Worksheets("Accepted").Range("D" & Rows.Count).End(xlUp).Row
    For k = 9 To Restrictedlastrow
        If ActiveWorkbook.Sheets("Accepted").Cells(k, 4).Value <> "Restricted" Then
        ActiveWorkbook.Sheets("Accepted").Cells(k, 4).Copy ActiveWorkbook.Sheets("Accepted").Cells(k, 5)
        ActiveWorkbook.Sheets("Accepted").Cells(k, 4).ClearContents
        End If
    Next k

'to reset settings back to normal
With Application
    .Calculation = xlCalculationAutomatic
    .ScreenUpdating = True
End With

Body:
Instead of

ActiveWorkbook.Sheets("Accepted").Cells(k, 4).Copy ActiveWorkbook.Sheets("Accepted").Cells(k, 5)

Use

ActiveWorkbook.Sheets("Accepted").Cells(k, 5) = ActiveWorkbook.Sheets("Accepted").Cells(k, 4)

Copy is an expensive operation. Since you seem to be interested only in a value of a cell, assign it directly (like you did in the previous loops).


问:
Searching Query in codeigniter with timestamp format
how do i compare date and time in codeigniter query where the database cell format is timestamp. i need to search data between date and between time. but date and time in my database in timestamp format. i have 4 inputs with datepicker and timepicker. datepicker format like "2017-06-06", and timepicker format like "16:00:00".  my database timestamp format looks like "2017-06-06 16:35:00.256". how do i compare my date and times with timestamp? big thanks for your help. sorry for my bad english. </p>

答:
```<code>  $start_date = date('Y-m-d'); //lets date this was your date

    //it would be something like below
    $query = $this->db->query(
        "SELECT FROM tbl_event WHERE event_startdate <= '{$start_date}'
        AND event_enddate >= '{$end_date}'");
</code>```


问:
Duplicate 'Content' items were included. The .NET SDK includes 'Content' items from your project directory by default
Whenever I add a javascript or css file to my asp.net core project and I execute dotnet run in my bash terminal, I get the following error:

/usr/share/dotnet/sdk/1.0.1/Sdks/Microsoft.NET.Sdk/build/Microsoft

.NET.Sdk.DefaultItems.targets(188,5): error : Duplicate 'Content'
  items were included. The .NET SDK includes 'Content' items from your
  project directory by default. You can either remove these items from
  your project file, or set the 'EnableDefaultContentItems' property to
  'false' if you want to explicitly include them in your project file.
  For more information, see https://aka.ms/sdkimplicititems. The
  duplicate items were: 'wwwroot/css/BasicQuotation.css';
  'wwwroot/js/BasicQuotation.js'
  [/mnt/c/Dev/myproject/MyProject/MyProject.csproj]

The build failed. Please fix the build errors and run again.

I can fix this by removing the ItemGroup from my csproj file, but I don't think that's very productive.

This happens in the default Visual Studio 2017 ASP.NET Core Web Application (.NET Core) template. I add the files to my project by right clicking the wwwroot > js folder and then select Add > New Item > JavaScript File

This is my .csproj file:

```<code><Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <PropertyGroup>
    <PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
  </PropertyGroup>

  <PropertyGroup>
    <UserSecretsId>aspnet-MyProject-7e1906d8-5dbd-469a-b237-d7a563081253</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <Compile Remove="wwwroot\lib\jquery-validation\**" />
    <Content Remove="wwwroot\lib\jquery-validation\**" />
    <EmbeddedResource Remove="wwwroot\lib\jquery-validation\**" />
    <None Remove="wwwroot\lib\jquery-validation\**" />
  </ItemGroup>

  <ItemGroup>
    <Content Include="wwwroot\css\BasicQuotation.css" />
    <Content Include="wwwroot\js\BasicQuotation.js" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" PrivateAssets="All" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0" PrivateAssets="All" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="1.0.0" />
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Data\Commands\" />
    <Folder Include="Data\Queries\" />
    <Folder Include="wwwroot\images\" />
  </ItemGroup>

</Project>
</code>```

答:
This worked in my case:</p>

```<code> <PropertyGroup>
    ...
    <EnableDefaultContentItems>false</EnableDefaultContentItems>
  </PropertyGroup>
</code>```

Body:
Whenever I add a javascript or css file to my asp.net core project and I execute dotnet run in my bash terminal, I get the following error:

/usr/share/dotnet/sdk/1.0.1/Sdks/Microsoft.NET.Sdk/build/Microsoft

.NET.Sdk.DefaultItems.targets(188,5): error : Duplicate 'Content'
  items were included. The .NET SDK includes 'Content' items from your
  project directory by default. You can either remove these items from
  your project file, or set the 'EnableDefaultContentItems' property to
  'false' if you want to explicitly include them in your project file.
  For more information, see https://aka.ms/sdkimplicititems. The
  duplicate items were: 'wwwroot/css/BasicQuotation.css';
  'wwwroot/js/BasicQuotation.js'
  [/mnt/c/Dev/myproject/MyProject/MyProject.csproj]

The build failed. Please fix the build errors and run again.

I can fix this by removing the ItemGroup from my csproj file, but I don't think that's very productive.

This happens in the default Visual Studio 2017 ASP.NET Core Web Application (.NET Core) template. I add the files to my project by right clicking the wwwroot > js folder and then select Add > New Item > JavaScript File

This is my .csproj file:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <PropertyGroup>
    <PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
  </PropertyGroup>

  <PropertyGroup>
    <UserSecretsId>aspnet-MyProject-7e1906d8-5dbd-469a-b237-d7a563081253</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <Compile Remove="wwwroot\lib\jquery-validation\**" />
    <Content Remove="wwwroot\lib\jquery-validation\**" />
    <EmbeddedResource Remove="wwwroot\lib\jquery-validation\**" />
    <None Remove="wwwroot\lib\jquery-validation\**" />
  </ItemGroup>

  <ItemGroup>
    <Content Include="wwwroot\css\BasicQuotation.css" />
    <Content Include="wwwroot\js\BasicQuotation.js" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" PrivateAssets="All" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0" PrivateAssets="All" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="1.0.0" />
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Data\Commands\" />
    <Folder Include="Data\Queries\" />
    <Folder Include="wwwroot\images\" />
  </ItemGroup>

</Project>

Body:
This worked in my case:

 <PropertyGroup>
    ...
    <EnableDefaultContentItems>false</EnableDefaultContentItems>
  </PropertyGroup>


问:
Fail to bind InAppBillingService when using IabHelper
I'm currently developing a game and try to implement In-app billing V3 of Google Play. I had followed the In-app sample and used IabHelper. However, when running the app in device, something goes wrong. I found that after mHelper.startSetup, neither onServiceDisconnected nor onServiceConnected was called. So I printed the result of mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); in the IabHelper Class. The result is false.

Here is my code:

```<code>private IabHelper mHelper;

// MainActivity onCreate
protected void onCreate(Bundle savedInstanceState){
    // ...
    mHelper = new IabHelper(this, base64EncodedPublicKey);
    mHelper.enableDebugLogging(true);
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                return;
            }

            if (mHelper == null) return;
        }
    });
}
</code>```

And in the method startSetup of IabHelper Class:

```<code>public void startSetup(final OnIabSetupFinishedListener listener) {
        // ...
        Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
        serviceIntent.setPackage("com.android.vending");
        if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
            // service available to handle that Intent
            boolean bRes = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
            // ### I printed the result here it was false
            Log.i("IAB", "IAB Service Result = " + bRes);
        }
        else {
            // no service available to handle that Intent
            if (listener != null) {
                listener.onIabSetupFinished(
                        new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
                        "Billing service unavailable on device."));
            }
        }
}
</code>```

I don't know the problem. I have done:

add permission: com.android.vending.BILLING

copy the .aidl file from sample to /src/com/android/vending/billing

my android target set to android-22

Any ideas what's wrong?
Thanks in advance.

答: Finally, I solved it by uploading the latest version of my game to developer console and debug the latest apk. The problem is gone. Hope this helps someone.</p>

Body:
I'm currently developing a game and try to implement In-app billing V3 of Google Play. I had followed the In-app sample and used IabHelper. However, when running the app in device, something goes wrong. I found that after mHelper.startSetup, neither onServiceDisconnected nor onServiceConnected was called. So I printed the result of mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); in the IabHelper Class. The result is false.

Here is my code:

private IabHelper mHelper;

// MainActivity onCreate
protected void onCreate(Bundle savedInstanceState){
    // ...
    mHelper = new IabHelper(this, base64EncodedPublicKey);
    mHelper.enableDebugLogging(true);
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                return;
            }

            if (mHelper == null) return;
        }
    });
}

And in the method startSetup of IabHelper Class:

public void startSetup(final OnIabSetupFinishedListener listener) {
        // ...
        Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
        serviceIntent.setPackage("com.android.vending");
        if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
            // service available to handle that Intent
            boolean bRes = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
            // ### I printed the result here it was false
            Log.i("IAB", "IAB Service Result = " + bRes);
        }
        else {
            // no service available to handle that Intent
            if (listener != null) {
                listener.onIabSetupFinished(
                        new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
                        "Billing service unavailable on device."));
            }
        }
}

I don't know the problem. I have done:

add permission: com.android.vending.BILLING

copy the .aidl file from sample to /src/com/android/vending/billing

my android target set to android-22

Any ideas what's wrong?
Thanks in advance.


问:
How to get a cells value in html table with JQuery
I seen a lot of post talk about my problem but any of one work for me.

I've this html table, I would to get the values under the cell (th) "Index".
How can I use jQuery for making this:

```<code><table id="htmlTable">
    <caption>Informations des hotspots</caption>
    <thead>
        <tr>
            <th>Index</th>
            <th>Nom du hotspot</th>
            <th>Image du hotspot</th>
        </tr>
    </thead>
    <tbody>
        <tr id="0">
            <td>0</td>
            <td>Hotspot Fribourg Centre</td>
            <td>../images/logos_hotspot/logo_wifi_centre.png</td>
            <td>
                <input type="button" value="supprimer" />
            </td>
        </tr>
        <tr id="1">
            <td>1</td>
            <td>Hotspot Avry Centre</td>
            <td>../images/logos_hotspot/logo_wifi_avry.png</td>
            <td>
                <input type="button" value="supprimer" />
            </td>
        </tr>
    </tbody>
</table>
</code>```

答:
Try the code below. </p>

```<code>$(document).on("click", "[id*=tableId] tr", function () {

   var a = $(this).find("td").eq(3).children().html();

   alert(a);
});
</code>```

Body:
I seen a lot of post talk about my problem but any of one work for me.

I've this html table, I would to get the values under the cell (th) "Index".
How can I use jQuery for making this:

Informations des hotspots

            Index
            Nom du hotspot
            Image du hotspot

            0
            Hotspot Fribourg Centre
            ../images/logos_hotspot/logo_wifi_centre.png

                <input type="button" value="supprimer" />

            1
            Hotspot Avry Centre
            ../images/logos_hotspot/logo_wifi_avry.png

                <input type="button" value="supprimer" />

Body:
Try the code below.

$(document).on("click", "[id*=tableId] tr", function () {

   var a = $(this).find("td").eq(3).children().html();

   alert(a);
});


问:
Arduino/C++ IF/ELSE statements
[Later Edit] I have a Arduino Uno together with an RFID-RC522, a servo motor and some LED's + I also made a aluminium foil sandwich/switch. Here is the code BEFORE THE ALUMINIUM SWITCH, with everything working perfect:

```<code>#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

#define SS_PIN 10 // SLAVE SELECT la DIGITAL 10
#define RST_PIN 9 // PIN RESET la DIGITAL 9
#define LED_V 5 //LED_Verde la D5
#define LED_R 4 //LED_Rosu la D4
#define BUZZER 2 //BUZZER la D2
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Creaza instanta MFRC522.
Servo bariera; //defineste nume Servo

void setup()
{
  Serial.begin(9600);   // Incepe comunicatia seriala cu PC-ul
  SPI.begin();      // Initializeaza bus-ul SPI
  mfrc522.PCD_Init();   // Initializeaza MFRC522
  bariera.attach(3); //servo pin
  bariera.write(0); //servo pozitie start
  pinMode(LED_V, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  noTone(BUZZER);
  Serial.println("Apropie cartela...[x][][]");
  delay(2500);
  Serial.println("Apropie cartela...[x][x][]");
  delay(3500);
  Serial.println("Apropie cartela...[x][x][x]");
  delay(4500);
  Serial.println("Astept raspuns utilzator!");
  Serial.println();

}
void loop()
{
  // Cauta cartele noi
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Selecteaza una dintre cartele
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Arata UID pe monitorul serial
  Serial.print("ID Tag/Cartela: ");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Mesaj : ");
  content.toUpperCase();
  if (content.substring(1) == "A0 B9 8D 7C") //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
  {
    Serial.println("Acces autorizat! Bine ati venit!");
    Serial.println();
    delay(500);
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    noTone(BUZZER);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }

 else   {
    Serial.println(" Access interzis! La revedere!");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 300);
    delay(1000);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);
  }
}
</code>```

So if the RFID CARD/TAG is "A0 B9 8D 7C", LED_V lights, short buzzer tone, and servo (here named bariera) goes to 120 degrees.

If the RFID CARD/TAG is NOT "A0 B9 8D 7C", LED_R lights, long buzzer tone and serv does nothing.

I also made an aluminium foil switch (two sheets of aluminium separated by cardboard, when pressed ((digitalRead(IESIRE)== 0) it should: LED_V lights, short buzzer tone, and servo (here named bariera) goes to 120 degrees.

This is the code for the whole thing with the switch included (#define IESIRE 6):

```<code>#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

#define SS_PIN 10 // SLAVE SELECT la DIGITAL 10
#define RST_PIN 9 // PIN RESET la DIGITAL 9
#define LED_V 5 //LED_Verde la D5
#define LED_R 4 //LED_Rosu la D4
#define BUZZER 2 //BUZZER la D2
#define IESIRE 6 // IESIRE la D6
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Creaza instanta MFRC522.
Servo bariera; //defineste nume Servo

void setup()
{
  Serial.begin(9600);   // Incepe comunicatia seriala cu PC-ul
  SPI.begin();      // Initializeaza bus-ul SPI
  mfrc522.PCD_Init();   // Initializeaza MFRC522
  bariera.attach(3); //servo pin
  bariera.write(0); //servo pozitie start
  pinMode(LED_V, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(IESIRE, INPUT);
  digitalWrite(IESIRE, HIGH);
  noTone(BUZZER);
  Serial.println("Apropie cartela...[x][][]");
  delay(2500);
  Serial.println("Apropie cartela...[x][x][]");
  delay(3500);
  Serial.println("Apropie cartela...[x][x][x]");
  delay(4500);
  Serial.println("Astept raspuns utilzator!");
  Serial.println();
}
void loop()
{
  // Cauta cartele noi
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Selecteaza una dintre cartele
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Arata UID pe monitorul serial
  Serial.print("ID Tag/Cartela: ");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Mesaj : ");
  content.toUpperCase();
  if (content.substring(1) == "A0 B9 8D 7C") //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
  {
    Serial.println("Acces autorizat! Bine ati venit!");
    Serial.println();
    delay(500);
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    noTone(BUZZER);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }

 else if (content.substring(1) != "A0 B9 8D 7C")    {
    Serial.println(" Access interzis! La revedere!");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 300);
    delay(1000);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);

 }

  else if ((content.substring(1) != "A0 B9 8D 7C") && (digitalRead(IESIRE)==0))     {
    Serial.println("Drum bun!");
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }
}
</code>```

Please ignore the else if statements and stuff, I'm fairly new to coding and I am trying my best. So if the switch is pressed (this translates to digitalRead(IESIRE)==0) )the servo need to go to 120 degrees, regardless of the other statements.

```<code>CARD/RFID TAG present > recognised > servo to 120 + led, buzzer
                present > not recognised > led, buzzer
 IF SWITCH is pressed > servo to 120 + led, buzzer REGARDLESS of the CARD stuff.
</code>```

I hope this makes sense and it's more explicit.

答:
Hard to tell what you mean by "the last part", but lets assume you're here:

```<code>else if (content.substring(1) != "A0 B9 8D 7C")    {
    /* stuff */
 }
 else if ((content.substring(1) != "A0 B9 8D 7C") && (digitalRead(IESIRE)==0))     {
    /* other stuff */
  }
</code>```

Lets simplify that:

```<code>else if (A)    {
    /* stuff */
 }
 else if (A && B)     {
    /* other stuff */
  }
</code>```

Can you see it now? If condition A is met the first bit is done and so the else if is ignored.

If the 2nd bit should always be done remove the "else if" so it is always checked. If it is a case of one or the other then put the more specific part (A && B) before the general case.

Also: for performance and dare I say clarity, don't call substr twice - store substr(...) != "..." in a variable and just use the variable. If you give it a sensible name like what != "A0 B9 8D 7C" actually means, your code becomes much clearer! You also avoid the hassle of having to change the string in 2 places should values changes etc.

edit:
So from the comments: ANYTIME digitalRead(IESIRE)==0 I want this to happen: Serial.println("Drum bun!"); digitalWrite(LED_V, HIGH); tone(BUZZER, 350); delay(300); bariera.write(120); ... (etc)

You should do this:

```<code>else if (content.substring(1) != "A0 B9 8D 7C")    {
    /* stuff */
 }

if (digitalRead(IESIRE)==0)     {
    /* other stuff */
  }
</code>```

Note it is not an else if and we've removed the redundant check that you don't care about.

Another edit:

I Think this does it. This is a good example of why DRY (Don't Repeat Yourself) is important. You've got one chunk of about 10 lines that is repeated for 2 conditions - it makes it that much harder to see shat is going on. Compare your original code to this simplified version of your code.

```<code>if (content.substring(1) == "A0 B9 8D 7C")  { //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
    doA();
  }
 else if (content.substring(1) != "A0 B9 8D 7C")    {
    do(B);
 }
  else if ((content.substring(1) != "A0 B9 8D 7C") && (digitalRead(IESIRE)==0))     {
    doA();
  }

 I think this is what you want:

 bool isRightCard = (content.substring(1) == "A0 B9 8D 7C");
 bool buttonPressed = digitalRead(IESIRE)==0;
 if (isRightCard || buttonPressed) //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
  {
    if (buttonPressed)
    {
        Serial.println("Drum bun!");
    }
    else
    {
        Serial.println("Acces autorizat! Bine ati venit!");
    }
    Serial.println();
    delay(500);
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    noTone(BUZZER);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }
 else {
    Serial.println(" Access interzis! La revedere!");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 300);
    delay(1000);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);

 }
</code>```

Title: Arduino/C++ IF/ELSE statements

Body:
[Later Edit] I have a Arduino Uno together with an RFID-RC522, a servo motor and some LED's + I also made a aluminium foil sandwich/switch. Here is the code BEFORE THE ALUMINIUM SWITCH, with everything working perfect:

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

#define SS_PIN 10 // SLAVE SELECT la DIGITAL 10
#define RST_PIN 9 // PIN RESET la DIGITAL 9
#define LED_V 5 //LED_Verde la D5
#define LED_R 4 //LED_Rosu la D4
#define BUZZER 2 //BUZZER la D2
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Creaza instanta MFRC522.
Servo bariera; //defineste nume Servo

void setup()
{
  Serial.begin(9600);   // Incepe comunicatia seriala cu PC-ul
  SPI.begin();      // Initializeaza bus-ul SPI
  mfrc522.PCD_Init();   // Initializeaza MFRC522
  bariera.attach(3); //servo pin
  bariera.write(0); //servo pozitie start
  pinMode(LED_V, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  noTone(BUZZER);
  Serial.println("Apropie cartela...[x][][]");
  delay(2500);
  Serial.println("Apropie cartela...[x][x][]");
  delay(3500);
  Serial.println("Apropie cartela...[x][x][x]");
  delay(4500);
  Serial.println("Astept raspuns utilzator!");
  Serial.println();

}
void loop()
{
  // Cauta cartele noi
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Selecteaza una dintre cartele
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Arata UID pe monitorul serial
  Serial.print("ID Tag/Cartela: ");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Mesaj : ");
  content.toUpperCase();
  if (content.substring(1) == "A0 B9 8D 7C") //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
  {
    Serial.println("Acces autorizat! Bine ati venit!");
    Serial.println();
    delay(500);
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    noTone(BUZZER);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }

 else   {
    Serial.println(" Access interzis! La revedere!");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 300);
    delay(1000);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);
  }
}

So if the RFID CARD/TAG is "A0 B9 8D 7C", LED_V lights, short buzzer tone, and servo (here named bariera) goes to 120 degrees.

If the RFID CARD/TAG is NOT "A0 B9 8D 7C", LED_R lights, long buzzer tone and serv does nothing.

I also made an aluminium foil switch (two sheets of aluminium separated by cardboard, when pressed ((digitalRead(IESIRE)== 0) it should: LED_V lights, short buzzer tone, and servo (here named bariera) goes to 120 degrees.

This is the code for the whole thing with the switch included (#define IESIRE 6):

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

#define SS_PIN 10 // SLAVE SELECT la DIGITAL 10
#define RST_PIN 9 // PIN RESET la DIGITAL 9
#define LED_V 5 //LED_Verde la D5
#define LED_R 4 //LED_Rosu la D4
#define BUZZER 2 //BUZZER la D2
#define IESIRE 6 // IESIRE la D6
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Creaza instanta MFRC522.
Servo bariera; //defineste nume Servo

void setup()
{
  Serial.begin(9600);   // Incepe comunicatia seriala cu PC-ul
  SPI.begin();      // Initializeaza bus-ul SPI
  mfrc522.PCD_Init();   // Initializeaza MFRC522
  bariera.attach(3); //servo pin
  bariera.write(0); //servo pozitie start
  pinMode(LED_V, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(IESIRE, INPUT);
  digitalWrite(IESIRE, HIGH);
  noTone(BUZZER);
  Serial.println("Apropie cartela...[x][][]");
  delay(2500);
  Serial.println("Apropie cartela...[x][x][]");
  delay(3500);
  Serial.println("Apropie cartela...[x][x][x]");
  delay(4500);
  Serial.println("Astept raspuns utilzator!");
  Serial.println();
}
void loop()
{
  // Cauta cartele noi
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Selecteaza una dintre cartele
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Arata UID pe monitorul serial
  Serial.print("ID Tag/Cartela: ");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Mesaj : ");
  content.toUpperCase();
  if (content.substring(1) == "A0 B9 8D 7C") //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
  {
    Serial.println("Acces autorizat! Bine ati venit!");
    Serial.println();
    delay(500);
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    noTone(BUZZER);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }

 else if (content.substring(1) != "A0 B9 8D 7C")    {
    Serial.println(" Access interzis! La revedere!");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 300);
    delay(1000);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);

 }

  else if ((content.substring(1) != "A0 B9 8D 7C") && (digitalRead(IESIRE)==0))     {
    Serial.println("Drum bun!");
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }
}

Please ignore the else if statements and stuff, I'm fairly new to coding and I am trying my best. So if the switch is pressed (this translates to digitalRead(IESIRE)==0) )the servo need to go to 120 degrees, regardless of the other statements.

CARD/RFID TAG present > recognised > servo to 120 + led, buzzer
                present > not recognised > led, buzzer
 IF SWITCH is pressed > servo to 120 + led, buzzer REGARDLESS of the CARD stuff.

I hope this makes sense and it's more explicit.

Body:
Hard to tell what you mean by "the last part", but lets assume you're here:

else if (content.substring(1) != "A0 B9 8D 7C")    {
    /* stuff */
 }
 else if ((content.substring(1) != "A0 B9 8D 7C") && (digitalRead(IESIRE)==0))     {
    /* other stuff */
  }

Lets simplify that:

else if (A)    {
    /* stuff */
 }
 else if (A && B)     {
    /* other stuff */
  }

Can you see it now? If condition A is met the first bit is done and so the else if is ignored.

If the 2nd bit should always be done remove the "else if" so it is always checked. If it is a case of one or the other then put the more specific part (A && B) before the general case.

Also: for performance and dare I say clarity, don't call substr twice - store substr(...) != "..." in a variable and just use the variable. If you give it a sensible name like what != "A0 B9 8D 7C" actually means, your code becomes much clearer! You also avoid the hassle of having to change the string in 2 places should values changes etc.

edit:
So from the comments: ANYTIME digitalRead(IESIRE)==0 I want this to happen: Serial.println("Drum bun!"); digitalWrite(LED_V, HIGH); tone(BUZZER, 350); delay(300); bariera.write(120); ... (etc)

You should do this:

else if (content.substring(1) != "A0 B9 8D 7C")    {
    /* stuff */
 }

if (digitalRead(IESIRE)==0)     {
    /* other stuff */
  }

Note it is not an else if and we've removed the redundant check that you don't care about.

Another edit:

I Think this does it. This is a good example of why DRY (Don't Repeat Yourself) is important. You've got one chunk of about 10 lines that is repeated for 2 conditions - it makes it that much harder to see shat is going on. Compare your original code to this simplified version of your code.

if (content.substring(1) == "A0 B9 8D 7C")  { //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
    doA();
  }
 else if (content.substring(1) != "A0 B9 8D 7C")    {
    do(B);
 }
  else if ((content.substring(1) != "A0 B9 8D 7C") && (digitalRead(IESIRE)==0))     {
    doA();
  }

 I think this is what you want:

 bool isRightCard = (content.substring(1) == "A0 B9 8D 7C");
 bool buttonPressed = digitalRead(IESIRE)==0;
 if (isRightCard || buttonPressed) //aici schimbam ID-ul (UID-ul) cartelelor autorizate, citite anterior pe monitorul serial
  {
    if (buttonPressed)
    {
        Serial.println("Drum bun!");
    }
    else
    {
        Serial.println("Acces autorizat! Bine ati venit!");
    }
    Serial.println();
    delay(500);
    digitalWrite(LED_V, HIGH);
    tone(BUZZER, 350);
    delay(300);
    noTone(BUZZER);
    bariera.write(120);
    delay(5000);
    bariera.write(0);
    digitalWrite(LED_V, LOW);

  }
 else {
    Serial.println(" Access interzis! La revedere!");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 300);
    delay(1000);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);

 }


问:
One Hot Encoding using numpy
If the input is zero I want to make an array which looks like this:

```<code>[1,0,0,0,0,0,0,0,0,0]
</code>```

and if the input is 5:

```<code>[0,0,0,0,0,1,0,0,0,0]
</code>```

For the above I wrote:

```<code>np.put(np.zeros(10),5,1)
</code>```

but it did not work.

Is there any way in which, this can be implemented in one line?

答:
I'm not sure the performance, but the following code works and it's neat.</p>

```<code>x = np.array([0, 5])
x_onehot = np.identity(6)[x]
</code>```

Title: One Hot Encoding using numpy

Body:
If the input is zero I want to make an array which looks like this:

[1,0,0,0,0,0,0,0,0,0]

and if the input is 5:

[0,0,0,0,0,1,0,0,0,0]

For the above I wrote:

np.put(np.zeros(10),5,1)

but it did not work.

Is there any way in which, this can be implemented in one line?

Body:
I'm not sure the performance, but the following code works and it's neat.

x = np.array([0, 5])
x_onehot = np.identity(6)[x]


问:
Rotating part of an image in 3D space
Here's the setup: This is for an ecommerce art site where some paintings are canvas transfers. The painting wraps around the sides and top and bottom of the canvas. We have high-res images of the entire painting, but what we want to display is a quasi-3D representation of the image in which you can see how the sides of the painting wrap around the canvas. Here's a rough sketch of what I'm talking about:

My question is, how can I rotate an image in 3D space? The approach I think I'd like to take, is to cut off a portion of the top and side of the image, and rotate then in 3D and then stich it back on to the top and side to give it the 3D look. How do I go about about doing that? It can be done using any .Net technology (GDI+, WPF etc.).

答:
I dont have any experience in this kind of stuff. But when i saw this question, the first thing comes to my mind is the funny Unicornify for SO.

In this making of article by balpha, he explained how the 2d unicorn sphere is rotated in 3d space.

But the code is written in python. If you are interested, you can take a look into that. But am not exactly sure this would help you.

Title: Rotating part of an image in 3D space